package cn.com.cifi.mars.service.impl;

import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import cn.com.cifi.mars.bean.bo.PriceValueCastDecisionEXTBO;
import cn.com.cifi.mars.bean.bo.SysLogBO;
import cn.com.cifi.mars.bean.vo.price.ApprovedDiffDetailVO;
import cn.com.cifi.mars.bean.vo.price.DifferenceReviewVO;
import cn.com.cifi.mars.bean.vo.price.DifferenceReviewVersionVO;
import cn.com.cifi.mars.bean.vo.price.GroupCorePriceDetailVO;
import cn.com.cifi.mars.bean.vo.price.GroupPriceDetailVO;
import cn.com.cifi.mars.bean.vo.price.GroupPriceVersionListVO;
import cn.com.cifi.mars.bean.vo.price.PriceCompareBasicInfoVO;
import cn.com.cifi.mars.bean.vo.price.PriceCompareVersionIdsVO;
import cn.com.cifi.mars.bean.vo.price.PriceDetailVO;
import cn.com.cifi.mars.bean.vo.price.PriceExcelExportVO;
import cn.com.cifi.mars.bean.vo.price.PriceNewestVersion;
import cn.com.cifi.mars.bean.vo.price.PriceSelectItemVO;
import cn.com.cifi.mars.bean.vo.price.PriceVersionListVO;
import cn.com.cifi.mars.bean.vo.price.ValueReviewVersionContentVO;
import cn.com.cifi.mars.bean.vo.price.req.PriceWarPlanReqParam;
import cn.com.cifi.mars.bean.vo.price.req.SavePriceHouseParam;
import cn.com.cifi.mars.bean.vo.price.req.SavePriceValueReqParam;
import cn.com.cifi.mars.common.exception.MsgException;
import cn.com.cifi.mars.constant.CodeEnum;
import cn.com.cifi.mars.constant.Constants;
import cn.com.cifi.mars.constant.CoreWarnItemEnum;
import cn.com.cifi.mars.constant.IsDeleteEnum;
import cn.com.cifi.mars.constant.IsSuccessEnum;
import cn.com.cifi.mars.constant.LogEventEnum;
import cn.com.cifi.mars.constant.LogSrcEnum;
import cn.com.cifi.mars.constant.LogTypeEnum;
import cn.com.cifi.mars.constant.MarketingEunm;
import cn.com.cifi.mars.constant.ModuleTypeEunm;
import cn.com.cifi.mars.constant.NumberEnum;
import cn.com.cifi.mars.constant.OperatorTypeEnum;
import cn.com.cifi.mars.constant.OrgTypeEunm;
import cn.com.cifi.mars.constant.ProcessingStateEnum;
import cn.com.cifi.mars.constant.SalyTypeEnum;
import cn.com.cifi.mars.constant.StageStatusEnum;
import cn.com.cifi.mars.constant.VersionCreateEnum;
import cn.com.cifi.mars.constant.VersionEventEnum;
import cn.com.cifi.mars.constant.VersionStatusEnum;
import cn.com.cifi.mars.constant.VersionTypeEunm;
import cn.com.cifi.mars.entity.ApprovalVersionCompare;
import cn.com.cifi.mars.entity.MdmProject;
import cn.com.cifi.mars.entity.MdmStage;
import cn.com.cifi.mars.entity.PriceCoreDetail;
import cn.com.cifi.mars.entity.PriceValueOrg;
import cn.com.cifi.mars.entity.PriceValueOrgGroup;
import cn.com.cifi.mars.entity.PriceVersion;
import cn.com.cifi.mars.entity.PriceVersionGroup;
import cn.com.cifi.mars.entity.StagePartNers;
import cn.com.cifi.mars.entity.SysNotice;
import cn.com.cifi.mars.entity.common.IdmUser;
import cn.com.cifi.mars.entity.common.SysDictionary;
import cn.com.cifi.mars.mapper.mars.PriceCoreDetailMapper;
import cn.com.cifi.mars.mapper.mars.PriceValueOrgGroupMapper;
import cn.com.cifi.mars.mapper.mars.PriceValueOrgMapper;
import cn.com.cifi.mars.mapper.mars.PriceVersionGroupMapper;
import cn.com.cifi.mars.mapper.mars.PriceVersionMapper;
import cn.com.cifi.mars.schedled.SupplyPlanTasks;
import cn.com.cifi.mars.service.CommonService;
import cn.com.cifi.mars.service.DmOdsNosTradedataviewformarsService;
import cn.com.cifi.mars.service.IdmUserService;
import cn.com.cifi.mars.service.PriceVersionService;
import cn.com.cifi.mars.service.PriceVersionValueOrgService;
import cn.com.cifi.mars.service.ProjectService;
import cn.com.cifi.mars.service.StagePartNersService;
import cn.com.cifi.mars.service.StageService;
import cn.com.cifi.mars.service.SupplyPlanVersionService;
import cn.com.cifi.mars.service.SysDictionaryService;
import cn.com.cifi.mars.service.SysLogService;
import cn.com.cifi.mars.service.SysNoticeService;
import cn.com.cifi.mars.service.VersionLogService;
import cn.com.cifi.mars.util.NumberUtils;
import cn.com.cifi.mars.util.PriceValueReportTemplate;
import cn.com.cifi.mars.util.ReportUtils;
import cn.com.cifi.mars.util.StrUtils;
import cn.com.cifi.mars.util.SynchrolockUtil;
import cn.com.cifi.mars.util.UUIDUtils;
import cn.com.cifi.mars.util.VersionNameUtils;
import cn.com.cifi.mars.util.VersionUtils;
import cn.com.cifi.mars.web.action.price.PriceMgrController;

@Service
public class PriceVersionServiceImpl extends ServiceImpl<PriceVersionMapper, PriceVersion> implements PriceVersionService {

    private static final Logger logger = LoggerFactory.getLogger(PriceMgrController.class);

    @Autowired
    private PriceVersionMapper priceVersionMapper;

    @Autowired
    private PriceValueOrgMapper priceValueOrgMapper;

    @Autowired
    private SysDictionaryService sysDictionaryService;

    @Autowired
    private SupplyPlanVersionService supplyPlanVersionService;

    @Autowired
    private StageService stageService;

    @Autowired
    private SysNoticeService sysNoticeService;

    @Autowired
    private SysLogService sysLogService;

    @Autowired
    private IdmUserService idmUserService;

    @Autowired
    private SubmitApprovedProjectServiceImpl submitApprovedProjectServiceImpl;

    @Autowired
    private ProjectService projectService;

    @Autowired
    private SupplyPlanTasks supplyPlanTasks;

    @Autowired
    private StagePartNersService stagePartNersService;

    @Autowired
    private VersionLogService versionLogService;

    @Autowired
    private CommonService commonService;

    @Autowired
    private DmOdsMyVsMarsSContractServiceImpl dmOdsMyVsMarsSContractServiceImpl;
    
    @Autowired
    private DmOdsNosTradedataviewformarsService dmOdsNosTradedataviewformarsService;

    @Autowired
    private SynchrolockUtil synchrolockUtil;

    @Autowired
    private PriceVersionValueOrgService priceVersionValueOrgService;
    
    @Autowired
    private PriceVersionGroupMapper priceVersionGroupMapper;
	@Autowired
	private PriceValueOrgGroupMapper priceValueOrgGroupMapper;
	@Autowired
	private PriceCoreDetailMapper priceCoreDetailMapper;

    static List<String> isParkList = Arrays.asList("139","140","141","142","154");


    /**
     * 获取货值信息
     * @param versionId 版本id
     * @return PriceSelectItemVO 查询版本信息
     */
    @Override
    public PriceSelectItemVO getPriceCastDecisionVersion(String versionId) {
        PriceSelectItemVO priceSelectItemVO = new PriceSelectItemVO();
        List<PriceDetailVO> resultList = new ArrayList<PriceDetailVO>();

        PriceVersion priceVersion = priceVersionMapper.selectByPrimaryKey(versionId);
        if (priceVersion != null) {

            //版本基础信息
            PriceVersionListVO priceVersionListVO = new PriceVersionListVO();
            setVersionInfo(priceVersion, priceVersionListVO);

            priceSelectItemVO.setVersionDetail(priceVersionListVO);

            //版本信息
            List<PriceDetailVO> groupList = new ArrayList<PriceDetailVO>();
            List<PriceDetailVO> batchList = new ArrayList<PriceDetailVO>();
            List<PriceDetailVO> productList = new ArrayList<PriceDetailVO>();
            List<PriceDetailVO> houseList = new ArrayList<PriceDetailVO>();
            List<PriceDetailVO> priceCastDecisionVOList = new ArrayList<PriceDetailVO>();
            List<PriceValueOrg> priceValueOrg = priceVersionMapper.selectOrgByVersionId(versionId, IsDeleteEnum.NO.getKey());
            if (CollectionUtils.isNotEmpty(priceValueOrg)) {
                wc : for (PriceValueOrg org : priceValueOrg) {
                    //去掉
                    String type = org.getType();
                    String businessType = org.getBusinessType();
                    if (orgEliminateInfo(priceVersion, type, businessType)){ continue wc;}

                    PriceDetailVO priceVO = setPriceDetailVOItemInfo(org, type, businessType);

                    if (type.equals(OrgTypeEunm.ORG_GROUP.getKey())) {
                        groupList.add(priceVO);
                    } else if (type.equals(OrgTypeEunm.ORG_BATCH.getKey())) {
                        batchList.add(priceVO);
                    } else if (type.equals(OrgTypeEunm.ORG_PRODUCT.getKey())) {
                        productList.add(priceVO);
                    } else if (type.equals(OrgTypeEunm.ORG_HOUSE_PACKAGE.getKey())) {
                        houseList.add(priceVO);
                    } else {
                        priceCastDecisionVOList.add(priceVO);
                    }
                }

                //排序
                orgSortInfo(resultList, groupList, batchList, productList, houseList);

                resultList.addAll(priceCastDecisionVOList);
            }

            priceSelectItemVO.setItems(resultList);

            return priceSelectItemVO;
        } else {
            throw new MsgException(CodeEnum.NON_VERSIONS);
        }
    }

    private void orgSortInfo(List<PriceDetailVO> resultList, List<PriceDetailVO> groupList, List<PriceDetailVO> batchList, List<PriceDetailVO> productList, List<PriceDetailVO> houseList) {
        if (CollectionUtils.isNotEmpty(groupList)) {
            groupAscSortInfo(groupList);
            resultList.addAll(groupList);
        }

        if (CollectionUtils.isNotEmpty(batchList)) {
            batchAscSortInfo(batchList);
            resultList.addAll(batchList);
        }

        if (CollectionUtils.isNotEmpty(productList)) {
            productAscSortInfo(productList);
            resultList.addAll(productList);
        }

        if (CollectionUtils.isNotEmpty(houseList)) {
            houseAscSortInfo(houseList);
            resultList.addAll(houseList);
        }
    }

    private void houseAscSortInfo(List<PriceDetailVO> houseList) {
        houseList.sort((a, b) -> {
            String aName = a.getAreaPart();
            String bName = b.getAreaPart();

            String aStr = "";
            String bStr = "";

            String[] aSplit = aName.split("-");
            String[] bSplit = bName.split("-");

            aStr = aSplit[0];
            bStr = bSplit[0];

            if (aName.equals(Constants.ORTHER_HOUSE_NAME)) {
                aStr = "10000000";
            }
            if (bName.equals(Constants.ORTHER_HOUSE_NAME)) {
                bStr = "10000000";
            }

            return aStr == null ? 1 : bStr == null ? -1 : Integer.valueOf(aStr) - Integer.valueOf(bStr);
        });
    }

    private void productAscSortInfo(List<PriceDetailVO> productList) {
        productList.sort((a, b) -> {
            String aCode = a.getCode();
            String bCode = b.getCode();

            return aCode == null ? 1 : bCode == null ? -1 : Integer.valueOf(aCode) - Integer.valueOf(bCode);
        });
    }

    private void batchAscSortInfo(List<PriceDetailVO> batchList) {
        batchList.sort((a, b) -> {
            String aName = a.getName();
            String bName = b.getName();

            String[] aStr = aName.split("批次");
            String[] bStr = bName.split("批次");

            String aValue = NumberEnum.getKeyByValue(aStr[0]);
            String bValue = NumberEnum.getKeyByValue(bStr[0]);

            return aValue == null ? 1 : bValue == null ? -1 : Integer.valueOf(aValue) - Integer.valueOf(bValue);
        });
    }

    private void groupAscSortInfo(List<PriceDetailVO> groupList) {
        groupList.sort((a, b) -> {
            return groupExportSortInfo(a.getName(), b.getName(), Constants.PARKING_NAME);
        });
    }

    private PriceDetailVO setPriceDetailVOItemInfo(PriceValueOrg org, String type, String businessType) {
        PriceDetailVO priceVO = new PriceDetailVO();
        priceVO.setId(org.getId());
        priceVO.setPid(org.getPid());
        priceVO.setName(org.getOrgName());
        priceVO.setCode(org.getOrgCode());
        priceVO.setType(type);
        priceVO.setIsParking(org.getIsParking());
        priceVO.setIsSupply(org.getIsSupply());
        priceVO.setSaleArea(org.getSaleArea());
        priceVO.setIsSplit(org.getIsSplit());

        if(org.getSupplyTimeVirtual() != null){
            priceVO.setSupplyDate(org.getSupplyTimeVirtual());
        }else{
            if (org.getSupplyTimeActual() != null) {
                priceVO.setSupplyDate(org.getSupplyTimeActual());
            } else {
                priceVO.setSupplyDate(org.getSupplyTime());
            }
        }

        priceVO.setBusinessTypeCode(businessType);
        priceVO.setBusinessTypeName(org.getBusinessTypeName());
        priceVO.setFreeTypeCode(org.getFreeType());
        priceVO.setFreeTypeName(org.getFreeTypeName());
        priceVO.setProTypeCode(org.getProType());
        priceVO.setProTypeName(org.getProTypeName());
        priceVO.setProProductCode(org.getProProductCode());
        priceVO.setProProductName(org.getProProductType());
        priceVO.setProductCode(org.getProductCode());
        priceVO.setProductName(org.getProductType());
        priceVO.setApartment(org.getApartment());
        priceVO.setAreaPart(org.getAreaPart());
        priceVO.setNum(org.getNum());
        priceVO.setNum_house(org.getRoomNum());
        priceVO.setNum_parking(org.getParkingNum());
        priceVO.setNum_parking_forsale(org.getForsaleParkingNum());
        priceVO.setAveragePrice_house_init(org.getAveragePriceHouseInit());
        priceVO.setAveragePrice_parking_init(org.getAveragePriceParkingInit());
        priceVO.setAveragePrice_house(org.getAveragePriceHouse());
        priceVO.setAveragePrice_parking(org.getAveragePriceParking());
        priceVO.setCommodityValue(org.getCommodityValue());
        priceVO.setNocontainCommodityValue(org.getNotCommodityValue());
        priceVO.setHousecontainCommodityValue(org.getHouseCommodityValue());
        return priceVO;
    }

    private boolean orgEliminateInfo(PriceVersion priceVersion, String type, String businessType) {
        if (priceVersion.getVersionType().equals(VersionTypeEunm.INVESTMENT.getKey())){
            if (type.equals(OrgTypeEunm.ORG_PRODUCT.getKey())){
                if (businessType.equals(SalyTypeEnum.NOT_RENTABLE.getKey()) || businessType.equals(SalyTypeEnum.RENTED.getKey())){
                    return true;
                }
            }
        }else{
            if (type.equals(OrgTypeEunm.ORG_BUILD.getKey())){
                if (businessType.equals(SalyTypeEnum.NOT_RENTABLE.getKey()) || businessType.equals(SalyTypeEnum.RENTED.getKey())){
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 删除货值版本
     * @param versionId 版本id
     * @param alias 操作人
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deletePriceVersion(String versionId, String alias) {

        PriceVersion priceVersion = priceVersionMapper.selectByPrimaryKey(versionId);
        if (priceVersion == null) {
            throw new MsgException(CodeEnum.NON_VERSIONS);
        }

        List<String> versionStateList = Arrays.asList(VersionStatusEnum.EXAMINEDAPPROVED.getKey(), VersionStatusEnum.APPROVED.getKey(), VersionStatusEnum.SUCCESSAPPROVED.getKey(), VersionStatusEnum.FAILUREAPPROVED.getKey(), VersionStatusEnum.SYSGENERATION.getKey());
        if (versionStateList.contains(priceVersion.getVersionState())) {
            throw new MsgException(CodeEnum.NON_DELETE_VERSIONS);
        }

        LocalDateTime now = LocalDateTime.now();
        priceVersionMapper.deteleVersionById(versionId, IsDeleteEnum.YES.getKey(), alias, now);
        priceVersionMapper.deteleOrgByVersionId(versionId, IsDeleteEnum.YES.getKey(), now);

        try{
            versionLogService.saveVersionLogInfo(priceVersion.getProjectId(), priceVersion.getProjectfId(), ModuleTypeEunm.PRICE.getKey(), VersionEventEnum.MANUAL_DELETE.getKey(),
                    priceVersion.getId(), VersionNameUtils.getVersionName(priceVersion), priceVersion.getVersionState(),
                    priceVersion.getVersionState(), "", null, alias, now, "货值删除版本", null, IsDeleteEnum.NO.getKey(), alias, now);
        }catch (Exception e){
            logger.error("################ delete price version versionLog error : "+e.getMessage(), e);
        }
    }

    /**
     * 保存货值信息
     * @param priceWarPlanReqParam
     * @param alias 操作人
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void savePriceCastDecisionVersion(PriceWarPlanReqParam priceWarPlanReqParam, String alias) {
        String versionId = priceWarPlanReqParam.getVersionId();
        LocalDateTime now = LocalDateTime.now();

        //价格版本状态为【待编制】、【编制中】、【待提交审批】、【审批驳回】状态时可进行价格编辑
        PriceVersion priceVersion = priceVersionMapper.selectByPrimaryKey(versionId);
        String versionState = priceVersion.getVersionState();
        List<String> versionStates = Arrays.asList(VersionStatusEnum.SUCCESSAPPROVED.getKey(), VersionStatusEnum.APPROVED.getKey(), VersionStatusEnum.SYSGENERATION.getKey());
        if (versionStates.contains(versionState)) {
            throw new MsgException(CodeEnum.NON_UPDATE_VERSIONS);
        }

        List<PriceValueOrg> updateValueOrgs = saveWarPlanPriceVersionItemInfo(priceWarPlanReqParam, versionId, now, priceWarPlanReqParam.getOrg_batch(), OrgTypeEunm.ORG_BATCH, priceWarPlanReqParam.getOrg_product(), OrgTypeEunm.ORG_PRODUCT);

        //查询字典面积段
        Map<String, SysDictionary> dictionaryAreaMap = new HashMap<String, SysDictionary>();
        List<SysDictionary> codes = sysDictionaryService.selectDictionaryByType(Arrays.asList("area_segmenta"));
        if (CollectionUtils.isNotEmpty(codes)){
            for (SysDictionary code : codes){
                dictionaryAreaMap.put(code.getDictValue(), code);
            }
        }

        List<PriceValueOrg> insertOrgs = new ArrayList<PriceValueOrg>();
        List<PriceValueOrg> updateOrgs = new ArrayList<PriceValueOrg>();
        List<String> deleteOrgs = new ArrayList<String>();
        List<SavePriceHouseParam> houseParam = priceWarPlanReqParam.getOrg_house();
        houseOrParkingSetPropertyMethod(versionId, now, insertOrgs, updateOrgs, deleteOrgs, houseParam, dictionaryAreaMap);

        String sourceVersionState = "";
        sourceVersionState = savePriceCastDecisionVersionInfo(alias, versionId, now, priceVersion, updateValueOrgs, insertOrgs, updateOrgs, deleteOrgs, sourceVersionState);

        try{
            versionLogService.saveVersionLogInfo(priceVersion.getProjectId(), priceVersion.getProjectfId(), ModuleTypeEunm.PRICE.getKey(), VersionEventEnum.UPDATE_SAVE.getKey(),
                    priceVersion.getId(), VersionNameUtils.getVersionName(priceVersion), sourceVersionState,
                    priceVersion.getVersionState(), "", null, alias, now, "货值保存版本", priceWarPlanReqParam.toString(), IsDeleteEnum.NO.getKey(), alias, now);
        }catch (Exception e){
            logger.error("################ save price version versionLog error : "+e);
        }
    }

    private String savePriceCastDecisionVersionInfo(String alias, String versionId, LocalDateTime now, PriceVersion priceVersion, List<PriceValueOrg> updateValueOrgs, List<PriceValueOrg> insertOrgs, List<PriceValueOrg> updateOrgs, List<String> deleteOrgs, String sourceVersionState) {
        if (StringUtils.isNotEmpty(versionId)) {
            sourceVersionState = priceVersion.getVersionState();
            if (priceVersion.getVersionState().equals(VersionStatusEnum.NOTPREPARED.getKey())){
                priceVersion.setVersionState(VersionStatusEnum.ORGANIZATION.getKey());
            }
            priceVersion.setUpdateBy(alias);
            priceVersion.setUpdateTime(now);
            priceVersionMapper.updateByPrimaryKeySelective(priceVersion);
        }

        if (CollectionUtils.isNotEmpty(updateOrgs)) {
            priceValueOrgMapper.updateBatch(updateOrgs);
        }

        if (CollectionUtils.isNotEmpty(insertOrgs)) {
            priceValueOrgMapper.insertBatch(insertOrgs);
        }

        if (CollectionUtils.isNotEmpty(deleteOrgs)) {
            priceValueOrgMapper.deleteOrgBatch(deleteOrgs, IsDeleteEnum.YES.getKey());
        }

        if (CollectionUtils.isNotEmpty(updateValueOrgs)) {
            priceValueOrgMapper.updateBatch(updateValueOrgs);
        }
        return sourceVersionState;
    }

    /**
     * 判断保存类型层级
     */
    private void houseOrParkingSetPropertyMethod(String versionId, LocalDateTime now, List<PriceValueOrg> insertOrgs, List<PriceValueOrg> updateOrgs, List<String> deleteOrgs, List<SavePriceHouseParam> houseParam, Map<String, SysDictionary> dictionaryAreaMap) {
        if (CollectionUtils.isNotEmpty(houseParam)) {
            for (SavePriceHouseParam param : houseParam) {

                //是否删除
                Boolean isDel = param.getIsDeleted();

                //是否新增
                Boolean isNew = param.getIsNew();

                if (isDel != null && isDel) {
                    houseOrParkingSetPropertyDelMethod(deleteOrgs, param);
                } else if (isNew != null && isNew) {
                    houseOrParkingSetPropertyInsertMethod(versionId, now, insertOrgs, dictionaryAreaMap, param);
                } else {
                    houseOrParkingSetPropertyUpdateMethod(now, updateOrgs, dictionaryAreaMap, param);
                }
            }
        }
    }

    private void houseOrParkingSetPropertyUpdateMethod(LocalDateTime now, List<PriceValueOrg> updateOrgs, Map<String, SysDictionary> dictionaryAreaMap, SavePriceHouseParam param) {
        PriceValueOrg org = new PriceValueOrg();
        org.setId(param.getId());
        org.setAveragePriceParking(param.getAveragePrice_parking());
        org.setAveragePriceHouse(param.getAveragePrice_house());
        if (StringUtils.isNotEmpty(param.getType()) && OrgTypeEunm.ORG_HOUSE_PACKAGE.getKey().equals(param.getType())) {
            if (!param.getAreaPart().equals(Constants.ORTHER_HOUSE_NAME)){
                org.setOrgName(dictionaryAreaMap.get(param.getAreaPart()).getDictName());
            }else{
                org.setOrgName(Constants.ORTHER_HOUSE_NAME);
            }
            org.setRoomNum(param.getNum_house());
            org.setIsParking(IsDeleteEnum.NO.getKey());
        }else if(StringUtils.isNotEmpty(param.getType()) && OrgTypeEunm.ORG_SALE_PACKAGE.getKey().equals(param.getType())){
            org.setOrgName(OrgTypeEunm.ORG_SALE_PACKAGE.getValue());
            org.setIsParking(IsDeleteEnum.YES.getKey());
        }else if (StringUtils.isNotEmpty(param.getType()) && OrgTypeEunm.ORG_NOT_SALE_PACKAGE.getKey().equals(param.getType())){
            org.setOrgName(OrgTypeEunm.ORG_NOT_SALE_PACKAGE.getValue());
            org.setIsParking(IsDeleteEnum.YES.getKey());
        }else if (StringUtils.isNotEmpty(param.getType()) && OrgTypeEunm.ORG_SALING_PARKING.getKey().equals(param.getType())){
            org.setOrgName(OrgTypeEunm.ORG_SALING_PARKING.getValue());
            org.setParkingNum(param.getNum_parking());
            org.setIsParking(IsDeleteEnum.YES.getKey());
        }else if (StringUtils.isNotEmpty(param.getType()) && OrgTypeEunm.ORG_NOT_SALING_PARKING.getKey().equals(param.getType())){
            org.setOrgName(OrgTypeEunm.ORG_NOT_SALING_PARKING.getValue());
            org.setIsParking(IsDeleteEnum.YES.getKey());
            org.setForsaleParkingNum(param.getNum_parking_forsale());
        }
        org.setAreaPart(param.getAreaPart());
        org.setSaleArea(param.getSaleArea());
        org.setHouseCommodityValue(param.getSum_house());
        org.setCommodityValue(param.getSum_parking_forsale());
        org.setNotCommodityValue(param.getSum_parking_saling());
        org.setUpdateTime(now);
        org.setIsEdit(param.getCanEditPrice());
        updateOrgs.add(org);
    }

    private void houseOrParkingSetPropertyInsertMethod(String versionId, LocalDateTime now, List<PriceValueOrg> insertOrgs, Map<String, SysDictionary> dictionaryAreaMap, SavePriceHouseParam param) {
        PriceValueOrg org = new PriceValueOrg();
        org.setId(UUIDUtils.create());
        org.setPid(param.getPid());
        org.setVersionId(versionId);
        org.setIsParking(IsDeleteEnum.YES.getKey());
        if (StringUtils.isNotEmpty(param.getType()) && OrgTypeEunm.ORG_SALE_PACKAGE.getKey().equals(param.getType())) {
            org.setType(OrgTypeEunm.ORG_SALE_PACKAGE.getKey());
            org.setOrgName(OrgTypeEunm.ORG_SALE_PACKAGE.getValue());
        } else if (StringUtils.isNotEmpty(param.getType()) && OrgTypeEunm.ORG_NOT_SALE_PACKAGE.getKey().equals(param.getType())) {
            org.setType(OrgTypeEunm.ORG_NOT_SALE_PACKAGE.getKey());
            org.setOrgName(OrgTypeEunm.ORG_NOT_SALE_PACKAGE.getValue());
        } else if (StringUtils.isNotEmpty(param.getType()) && OrgTypeEunm.ORG_SALING_PARKING.getKey().equals(param.getType())) {
            org.setType(OrgTypeEunm.ORG_SALING_PARKING.getKey());
            org.setOrgCode(OrgTypeEunm.ORG_SALING_PARKING.getKey());
            org.setOrgName(OrgTypeEunm.ORG_SALING_PARKING.getValue());
            org.setParkingNum(param.getNum_parking());
            org.setIsParking(IsDeleteEnum.YES.getKey());
        } else if (StringUtils.isNotEmpty(param.getType()) && OrgTypeEunm.ORG_HOUSE_PACKAGE.getKey().equals(param.getType())) {
            org.setType(OrgTypeEunm.ORG_HOUSE_PACKAGE.getKey());
            org.setOrgCode(OrgTypeEunm.ORG_HOUSE_PACKAGE.getKey());
            if (!param.getAreaPart().equals(Constants.ORTHER_HOUSE_NAME)){
                org.setOrgName(dictionaryAreaMap.get(param.getAreaPart()).getDictName());
            }else{
                org.setOrgName(Constants.ORTHER_HOUSE_NAME);
            }
            org.setAreaPart(param.getAreaPart());
            org.setSaleArea(param.getSaleArea());
            org.setIsParking(IsDeleteEnum.NO.getKey());
            org.setRoomNum(param.getNum_house());
        } else if(StringUtils.isNotEmpty(param.getType()) && OrgTypeEunm.ORG_NOT_SALING_PARKING.getKey().equals(param.getType())){
            org.setType(OrgTypeEunm.ORG_NOT_SALING_PARKING.getKey());
            org.setOrgCode(OrgTypeEunm.ORG_NOT_SALING_PARKING.getKey());
            org.setOrgName(OrgTypeEunm.ORG_NOT_SALING_PARKING.getValue());
            org.setIsParking(IsDeleteEnum.YES.getKey());
            org.setForsaleParkingNum(param.getNum_parking_forsale());
        }
        org.setAveragePriceHouse(param.getAveragePrice_house());
        org.setAveragePriceParking(param.getAveragePrice_parking());
        org.setHouseCommodityValue(param.getSum_house());
        org.setCommodityValue(param.getSum_parking_forsale());
        org.setNotCommodityValue(param.getSum_parking_saling());
        org.setIsDelete(IsDeleteEnum.NO.getKey());
        org.setIsSplit(param.getIsSplit());
        org.setIsEdit(param.getCanEditPrice());
        org.setCreateTime(now);
        org.setUpdateTime(now);

        insertOrgs.add(org);
    }

    private void houseOrParkingSetPropertyDelMethod(List<String> deleteOrgs, SavePriceHouseParam param) {
        String hoseId = param.getId();
        if (StringUtils.isNotEmpty(hoseId.trim())) {
            deleteOrgs.add(hoseId);
        }
    }

    /**
     *  priceValueOrg赋值
     */
    private void orgValuePropertySetMethod(String versionId, String type, LocalDateTime now, SavePriceValueReqParam productParam, PriceValueOrg priceValueOrg) {
        priceValueOrg.setId(productParam.getId());
        priceValueOrg.setVersionId(versionId);
        priceValueOrg.setType(type);
        priceValueOrg.setAveragePriceHouse(productParam.getAveragePrice_house());
        priceValueOrg.setAveragePriceParking(productParam.getAveragePrice_parking());
        priceValueOrg.setRoomNum(productParam.getNum_house());
        priceValueOrg.setParkingNum(productParam.getNum_parking());
        priceValueOrg.setForsaleParkingNum(productParam.getNum_parking_forsale());
        priceValueOrg.setHouseCommodityValue(productParam.getSum_house());
        priceValueOrg.setCommodityValue(productParam.getSum_parking_forsale());
        priceValueOrg.setNotCommodityValue(productParam.getSum_parking_saling());
        priceValueOrg.setSaleArea(productParam.getSaleArea());
        priceValueOrg.setIsEdit(productParam.getCanEditPrice());
        priceValueOrg.setUpdateTime(now);
    }

    /**
     *  获取货值版本列表
     * @param projectFid 分期id
     * @param versionType 版本类型
     * @return List<PriceVersionListVO>
     */
    @Override
    public List<PriceVersionListVO> getPriceVersionInfo(String projectFid, String versionType) {
        List<PriceVersionListVO> priceVersionList = priceVersionMapper.selectByProjectFidAndType(projectFid, versionType, IsDeleteEnum.NO.getKey());

        if (CollectionUtils.isEmpty(priceVersionList)) {
            throw new MsgException(CodeEnum.NON_EXISTENT_VERSIONS);
        }

        return priceVersionList;
    }


    /**
     * 保存货值信息
     * @param priceWarPlanReqParam
     * @param alias 操作人
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveWarPlanPriceVersion(PriceWarPlanReqParam priceWarPlanReqParam, String alias) {
        String versionId = priceWarPlanReqParam.getVersionId();
        LocalDateTime now = LocalDateTime.now();

        //价格版本状态为【待编制】、【编制中】、【待提交审批】、【审批驳回】状态时可进行价格编辑
        PriceVersion priceVersion = priceVersionMapper.selectByPrimaryKey(versionId);
        String versionState = priceVersion.getVersionState();
        List<String> versionStates = Arrays.asList(VersionStatusEnum.SUCCESSAPPROVED.getKey(), VersionStatusEnum.APPROVED.getKey(), VersionStatusEnum.SYSGENERATION.getKey());
        if (versionStates.contains(versionState)) {
            throw new MsgException(CodeEnum.NON_UPDATE_VERSIONS);
        }

        //保存各节点下的货值信息
        List<PriceValueOrg> updateValueOrgs = saveWarPlanPriceVersionItemInfo(priceWarPlanReqParam, versionId, now, priceWarPlanReqParam.getOrg_product(), OrgTypeEunm.ORG_PRODUCT, priceWarPlanReqParam.getOrg_build(), OrgTypeEunm.ORG_BUILD);

        //查询字典面积段
        Map<String, SysDictionary> dictionaryAreaMap = new HashMap<String, SysDictionary>();
        List<SysDictionary> codes = sysDictionaryService.selectDictionaryByType(Arrays.asList("area_segmenta"));
        if (CollectionUtils.isNotEmpty(codes)){
            for (SysDictionary code : codes){
                dictionaryAreaMap.put(code.getDictValue(), code);
            }
        }

        List<PriceValueOrg> insertOrgs = new ArrayList<PriceValueOrg>();
        List<PriceValueOrg> updateOrgs = new ArrayList<PriceValueOrg>();
        List<String> deleteOrgs = new ArrayList<String>();
        List<SavePriceHouseParam> houseParam = priceWarPlanReqParam.getOrg_house();
        houseOrParkingSetPropertyMethod(versionId, now, insertOrgs, updateOrgs, deleteOrgs, houseParam, dictionaryAreaMap);

        String sourceVersionState = "";
        sourceVersionState = saveWarPlanPriceVersionInfo(alias, versionId, now, priceVersion, updateValueOrgs, insertOrgs, updateOrgs, deleteOrgs, sourceVersionState);

        try{
            versionLogService.saveVersionLogInfo(priceVersion.getProjectId(), priceVersion.getProjectfId(), ModuleTypeEunm.PRICE.getKey(), VersionEventEnum.UPDATE_SAVE.getKey(),
                    priceVersion.getId(), VersionNameUtils.getVersionName(priceVersion), sourceVersionState,
                    priceVersion.getVersionState(), "", null, alias, now, "货值保存版本", priceWarPlanReqParam.toString(), IsDeleteEnum.NO.getKey(), alias, now);
        }catch (Exception e){
            logger.error("################ save price version versionLog error : "+e);
        }
    }

    private String saveWarPlanPriceVersionInfo(String alias, String versionId, LocalDateTime now, PriceVersion priceVersion, List<PriceValueOrg> updateValueOrgs, List<PriceValueOrg> insertOrgs, List<PriceValueOrg> updateOrgs, List<String> deleteOrgs, String sourceVersionState) {
        if (StringUtils.isNotEmpty(versionId)) {
            sourceVersionState = priceVersion.getVersionState();
            if (priceVersion.getVersionState().equals(VersionStatusEnum.NOTPREPARED.getKey())){
                priceVersion.setVersionState(VersionStatusEnum.ORGANIZATION.getKey());
            }
            priceVersion.setUpdateTime(now);
            priceVersion.setUpdateBy(alias);
            priceVersionMapper.updateByPrimaryKeySelective(priceVersion);
        }

        if (CollectionUtils.isNotEmpty(updateOrgs)) {
            priceValueOrgMapper.updateBatch(updateOrgs);
        }

        if (CollectionUtils.isNotEmpty(insertOrgs)) {
            priceValueOrgMapper.insertBatch(insertOrgs);
        }

        if (CollectionUtils.isNotEmpty(deleteOrgs)) {
            priceValueOrgMapper.deleteOrgBatch(deleteOrgs, IsDeleteEnum.YES.getKey());
        }

        if (CollectionUtils.isNotEmpty(updateValueOrgs)) {
            priceValueOrgMapper.updateBatch(updateValueOrgs);
        }
        return sourceVersionState;
    }

    private List<PriceValueOrg> saveWarPlanPriceVersionItemInfo(PriceWarPlanReqParam priceWarPlanReqParam, String versionId, LocalDateTime now, List<SavePriceValueReqParam> org_product, OrgTypeEunm orgProduct, List<SavePriceValueReqParam> org_build, OrgTypeEunm orgBuild) {
        List<PriceValueOrg> updateValueOrgs = new ArrayList<PriceValueOrg>();
        List<SavePriceValueReqParam> projectfParams = priceWarPlanReqParam.getOrg_stage();
        if (CollectionUtils.isNotEmpty(projectfParams)) {
            for (SavePriceValueReqParam groupParam : projectfParams) {
                PriceValueOrg priceValueOrg = new PriceValueOrg();
                orgValuePropertySetMethod(versionId, OrgTypeEunm.ORG_STAGE.getKey(), now, groupParam, priceValueOrg);

                updateValueOrgs.add(priceValueOrg);
            }
        }
        List<SavePriceValueReqParam> groupParams = priceWarPlanReqParam.getOrg_group();
        if (CollectionUtils.isNotEmpty(groupParams)) {
            for (SavePriceValueReqParam groupParam : groupParams) {
                PriceValueOrg priceValueOrg = new PriceValueOrg();
                orgValuePropertySetMethod(versionId, OrgTypeEunm.ORG_GROUP.getKey(), now, groupParam, priceValueOrg);

                updateValueOrgs.add(priceValueOrg);
            }
        }
        List<SavePriceValueReqParam> productParams = org_product;
        if (CollectionUtils.isNotEmpty(productParams)) {
            for (SavePriceValueReqParam productParam : productParams) {
                PriceValueOrg priceValueOrg = new PriceValueOrg();
                orgValuePropertySetMethod(versionId, orgProduct.getKey(), now, productParam, priceValueOrg);

                updateValueOrgs.add(priceValueOrg);
            }
        }
        List<SavePriceValueReqParam> buildParams = org_build;
        if (CollectionUtils.isNotEmpty(buildParams)) {
            for (SavePriceValueReqParam buildParam : buildParams) {
                PriceValueOrg priceValueOrg = new PriceValueOrg();
                orgValuePropertySetMethod(versionId, orgBuild.getKey(), now, buildParam, priceValueOrg);

                updateValueOrgs.add(priceValueOrg);
            }
        }
        return updateValueOrgs;
    }

    /**
     *  修改货值版本状态
     * @param versionId 版本id
     * @param versionState 版本状态
     * @param alias 操作人
     * @param nowSize 条数
     * @param totalSize 总数
     */
    @Override
    public void updateStateById(String versionId, String versionState, String alias, String nowSize, String totalSize) {
        logger.info("#####################    updateStateById  start:"+LocalDateTime.now());
        logger.info("#####################    updateStateById  versionId:"+versionId);
        logger.info("#####################    updateStateById  alias:"+alias);
        logger.info("#####################    updateStateById  versionState:"+versionState);

        PriceVersion priceVersion = updatePriceVersionStatusInfo(versionState, alias, versionId);

        IdmUser user = getIdmUser(alias);
        logger.info("#####################    updateStateById  user:"+user.toString());

        if (versionState.equals(VersionStatusEnum.SUCCESSAPPROVED.getKey())) {

            LocalDateTime now = LocalDateTime.now();
            int year = now.getYear();
            Month month = now.getMonth();
            int day = now.getDayOfMonth();
            int hour = now.getHour();

            //动态版本审批通过是检查版本归属月份
            if(priceVersion.getVersionType().equals(VersionTypeEunm.DYNAMIC.getKey())){
                logger.info("#####################    updateStateById  versionType:"+priceVersion.getVersionType());

                LocalDate oldAscriptionDate = priceVersion.getAscriptionDate();
                int ascriptionDateYear = oldAscriptionDate.getYear();
                Month ascriptionDateMonth = oldAscriptionDate.getMonth();

                if(ascriptionDateYear != year || !ascriptionDateMonth.equals(month)){
                    if (day == Constants.ONE && hour <= Constants.SIX){//一号6点前
                    }else{
                        try{
                            changeDynamicAscriptDateInfo(priceVersion);
                        }catch (Exception e){
                            logger.error("#######################     updateStateById   dynamic  updateByPrimaryKeySelective  error:"+e.getMessage(), e);
                        }
                    }
                }
            }else if (priceVersion.getVersionType().equals(VersionTypeEunm.INVESTMENT.getKey())){
                LocalDate oldAscriptionDate = priceVersion.getAscriptionDate();
                int ascriptionDateYear = oldAscriptionDate.getYear();
                Month ascriptionDateMonth = oldAscriptionDate.getMonth();

                if(ascriptionDateYear != year || !ascriptionDateMonth.equals(month)){
                    try{
                        changeInvestmentAscriptDateInfo(priceVersion);
                    }catch (Exception e){
                        logger.error("#######################     updateStateById   investment   updateByPrimaryKeySelective  error:"+e.getMessage(), e);
                    }
                }
            }

            PriceVersion vs = priceValueOrgMapper.selectNotDelById(versionId, IsDeleteEnum.NO.getKey());
            try{
                if (vs != null) {
                    logger.info("#######################     updateStateById  vs:"+vs.toString());
                    supplyPlanVersionService.createSupplyPlanVersion(versionId, vs.getVersionType(), Constants.SYS);
                }
            }catch (Exception e){
                logger.error("#######################     updateStateById  createSupplyPlanVersion  error:"+e.getMessage(), e);
            }

            //处理货值代办
            if (vs != null) {
                List<SysNotice> notices = sysNoticeService.selectModeByProjectFidAndVersionType(vs.getProjectfId(), ModuleTypeEunm.PRICE.getKey(), vs.getVersionType(), ProcessingStateEnum.UNTREATED.getKey(), IsDeleteEnum.NO.getKey());
                if (CollectionUtils.isNotEmpty(notices)) {
                    //刷新楼栋计划信息
                    clearUpNoticeInfo(user, vs.getProjectfId(), vs.getVersionType(), notices);
                }
            }
        }
    }

    /**
     * 修改版本状态
     */
    @Override
    public void updateStateById(List<String> versionIds, String versionState, String alias) {
        String projectFid = "";
        List<PriceVersion> priceVersionList = new ArrayList<PriceVersion>();
        if (CollectionUtils.isNotEmpty(versionIds)){
            for (String versionId : versionIds){
                PriceVersion priceVersion = updatePriceVersionStatusInfo(versionState, alias, versionId);
                projectFid = priceVersion.getProjectfId();
                priceVersionList.add(priceVersion);
            }
        }

        IdmUser user = getIdmUser(alias);

        if (versionState.equals(VersionStatusEnum.SUCCESSAPPROVED.getKey())
            || versionState.equals(VersionStatusEnum.FAILUREAPPROVED.getKey())
            || versionState.equals(VersionStatusEnum.ORGANIZATION.getKey())) {

            LocalDateTime now = LocalDateTime.now();
            int year = now.getYear();
            Month month = now.getMonth();
            int day = now.getDayOfMonth();
            int hour = now.getHour();

            //动态版本审批通过是检查版本归属月份
            if (CollectionUtils.isNotEmpty(priceVersionList)){

                List<MdmStage> stages = stageService.selectStagesByprojectFid(projectFid);
                List<String> stageIds = Optional.of(stages).orElseGet(ArrayList::new)
                        .stream().map(MdmStage::getProjectFid)
                        .collect(Collectors.toList());
                for (PriceVersion priceVersion : priceVersionList){

                    String versionId = priceVersion.getId();
                    stageIds.remove(priceVersion.getProjectfId());

                    //审批通过货值变更归属月份
                    if (versionState.equals(VersionStatusEnum.SUCCESSAPPROVED.getKey())){
                        if(priceVersion.getVersionType().equals(VersionTypeEunm.DYNAMIC.getKey())){

                            LocalDate oldAscriptionDate = priceVersion.getAscriptionDate();
                            int ascriptionDateYear = oldAscriptionDate.getYear();
                            Month ascriptionDateMonth = oldAscriptionDate.getMonth();

                            if(ascriptionDateYear != year || !ascriptionDateMonth.equals(month)){
                                if (day == Constants.ONE && hour <= Constants.SIX){//一号6点前
                                    logger.info("#####################    updateStateById  now:"+now);
                                }else{
                                    try{
                                        changeDynamicAscriptDateInfo(priceVersion);
                                    }catch (Exception e){
                                        logger.error("#######################     updateStateById   dynamic  updateByPrimaryKeySelective  error:"+e.getMessage(), e);
                                    }
                                }
                            }
                        }else if (priceVersion.getVersionType().equals(VersionTypeEunm.INVESTMENT.getKey())){
                            LocalDate oldAscriptionDate = priceVersion.getAscriptionDate();
                            int ascriptionDateYear = oldAscriptionDate.getYear();
                            Month ascriptionDateMonth = oldAscriptionDate.getMonth();

                            if(ascriptionDateYear != year || !ascriptionDateMonth.equals(month)){
                                try{
                                    changeInvestmentAscriptDateInfo(priceVersion);
                                }catch (Exception e){
                                    logger.error("#######################     updateStateById   investment   updateByPrimaryKeySelective  error:"+e.getMessage(), e);
                                }
                            }
                        }
                    }

                    //审批通过生成供货计划
                    if (versionState.equals(VersionStatusEnum.SUCCESSAPPROVED.getKey())){
                        PriceVersion vs = priceValueOrgMapper.selectNotDelById(versionId, IsDeleteEnum.NO.getKey());
                        try{
                            if (vs != null) {
                                supplyPlanVersionService.createSupplyPlanVersion(versionId, vs.getVersionType(), Constants.SYS);
                            }
                        }catch (Exception e){
                            logger.error("#######################     updateStateById  createSupplyPlanVersion  error:"+e.getMessage(), e);
                        }
                    }

                    //编制中(审批废弃)、审批驳回和审批通过处理货值代办
                    List<SysNotice> notices = sysNoticeService.selectModeByProjectFidAndVersionType(priceVersion.getProjectfId(), ModuleTypeEunm.PRICE.getKey(), priceVersion.getVersionType(), ProcessingStateEnum.UNTREATED.getKey(),IsDeleteEnum.NO.getKey());
                    if(CollectionUtils.isNotEmpty(notices)){
                        //清除待办信息
                        clearUpNoticeInfo(user, priceVersion.getProjectfId(), priceVersion.getVersionType(), notices);
                    }
                }
            }
        }
    }

    /**
     *  清除同类型待办和消除门户待办
     */
    private void clearUpNoticeInfo(IdmUser user, String projectFId, String versionType, List<SysNotice> notices) {
        Thread refreshPriceVersionByUpdateState = new RefreshPriceVersionByUpdateState(versionType, projectFId, null);
        refreshPriceVersionByUpdateState.start();

        for (SysNotice notice : notices) {
            logger.info("#####################    updateStateById  notice:"+notice.toString());

            try {
                //系统将该项目分期之前同类待办设置为无效待办，同时删除新门户该分期之前同类待办
                sysNoticeService.updateNoticeStateByStageIdAndType(projectFId, ModuleTypeEunm.PRICE.getKey(), versionType, ProcessingStateEnum.FAILURE.getKey(), Constants.SYS, LocalDateTime.now(), IsDeleteEnum.NO.getKey());

                String instanceId = notice.getPortalInstanceId();
                logger.info("#####################    updateStateById  instanceId:"+instanceId);

                //删除门户代办消息
                if (StringUtils.isNotEmpty(instanceId)) {
                    commonService.updatePortalProcess(instanceId, OperatorTypeEnum.TRANSFERRED_TO_OFFICE.getKey(), user, null);
                }
            } catch (Exception e) {
                logger.error("#######################     updateStateById  updatePortalProcess  error:" + e.getMessage(), e);
            }
        }
    }

    /**
     * 货值投资版版本变更归属月
     */
    @Transactional(rollbackFor=Exception.class)
    private void changeInvestmentAscriptDateInfo(PriceVersion priceVersion) {
        LocalDate newAscriptionDate = LocalDate.now();
        priceVersion.setAscriptionDate(newAscriptionDate);
        priceVersionMapper.updateByPrimaryKeySelective(priceVersion);

        saveLog(LogEventEnum.EDIT, "货值管理", "投资版货值审批变更归宿月", priceVersion.getId(), IsSuccessEnum.SUCCESS.getKey());
    }

    /**
     * 货值动态版版本变更归属月
     */
    @Transactional(rollbackFor=Exception.class)
    private void changeDynamicAscriptDateInfo(PriceVersion priceVersion) {
        LocalDate newAscriptionDate = LocalDate.now();
        priceVersion.setAscriptionDate(newAscriptionDate);
        String oldVersionId = null;
        String oldVersionNum = null;
        PriceVersion monthNewestPriceVersion = priceVersionMapper.selectNewestDynamicToMonthByPriceAndStatus(priceVersion.getProjectfId(), priceVersion.getVersionType(), newAscriptionDate,
                Arrays.asList(VersionStatusEnum.SUCCESSAPPROVED.getKey(), VersionStatusEnum.SYSGENERATION.getKey()), IsDeleteEnum.NO.getKey());
        if (monthNewestPriceVersion != null) {
            oldVersionId = monthNewestPriceVersion.getId();
            oldVersionNum = monthNewestPriceVersion.getVersionNum();
        }

        String newVersionNum = VersionUtils.bigVersionInc(oldVersionNum);
        priceVersion.setVersionNum(newVersionNum);
        DateFormat df = new SimpleDateFormat("yyyy-MM");
        priceVersion.setVersionName(df.format(new Date()) + "月动态版" + newVersionNum);
        priceVersion.setPreVersionId(oldVersionId);
        priceVersion.setPreVersionNum(oldVersionNum);

        priceVersionMapper.updateByPrimaryKeySelective(priceVersion);

        saveLog(LogEventEnum.EDIT, "货值管理", "动态版货值审批变更归宿月", priceVersion.getId(), IsSuccessEnum.SUCCESS.getKey());
    }

    /**
     * 获取操作人，如果为空则为系统
     */
    private IdmUser getIdmUser(String alias) {
        IdmUser user = new IdmUser();
        if (StringUtils.isNotEmpty(alias)) {
            user = idmUserService.getByAlias(alias);
            if (null == user) {
                user = new IdmUser();
                user.setAlias(Constants.SYS);
                user.setUsercn(Constants.SYS_NAME);
            }
        } else {
            user.setAlias(Constants.SYS);
            user.setUsercn(Constants.SYS_NAME);
        }
        return user;
    }

    /**
     * 修改货值版本状态
     * @return
     */
    @Transactional(rollbackFor=Exception.class)
    private PriceVersion updatePriceVersionStatusInfo(String versionState, String alias, String versionId) {
        PriceVersion priceVersion = priceVersionMapper.selectByPrimaryKey(versionId);
        if (null == priceVersion) {
            throw new MsgException(CodeEnum.NON_EXISTENT_VERSIONS_ORG);
        }else{
            String extVersionState = priceVersion.getVersionState();
            if (extVersionState.equals(VersionStatusEnum.SUCCESSAPPROVED.getKey())){
                throw new MsgException(CodeEnum.NON_EXISTENT_VERSIONS_STATE);
            }
        }

        try {
            priceVersion.setId(versionId);
            priceVersion.setVersionState(versionState);
            priceVersion.setUpdateBy(alias);
            priceVersion.setUpdateTime(LocalDateTime.now());
            priceVersionMapper.updateByPrimaryKeySelective(priceVersion);
        } catch (Exception e) {
            logger.error("#######################     updateStateById  updateState  error:" + e.getMessage(), e);
        }
        return priceVersion;
    }

    class RefreshPriceVersionByUpdateState extends Thread{

        private String versionType;
        private String stageId;
        private String instId;

        public RefreshPriceVersionByUpdateState(String versionType,String stageId,String instId) {
            this.versionType=versionType;
            this.stageId=stageId;
            this.instId=instId;
        }

        public void run() {
            long startTime=System.currentTimeMillis();

            boolean isLocked = synchrolockUtil.islocked(Constants.RedisSyncKey);
            logger.info("====同步锁加锁状态："+isLocked);

            try {
                if (versionType.equals(VersionTypeEunm.INVESTMENT.getValue())) {
                    priceVersionValueOrgService.panoCastDecisionVersionChange(stageId, instId);
                } else {
                    priceVersionValueOrgService.panoDynamicVersionChange(stageId, VersionTypeEunm.getKey(versionType), "pano", instId);
                }
            } catch (Exception e) {
                logger.error("####################  货值审批待办信息错误 error :" + e.getMessage(), e);
            }finally {
                synchrolockUtil.unlock(Constants.RedisSyncKey);

                long endTime=System.currentTimeMillis();
                logger.info("##################     RefreshPriceVersionByUpdateState  time:"+(endTime - startTime)+"ms");
                logger.info("====同步锁解锁成功====");
            }
        }
    }

    /**
     * 保存货值日志信息
     */
    private boolean saveLog(LogEventEnum event, String module, String title, String content, String isSuccess) {
        SysLogBO bo = new SysLogBO();
        bo.setEvent(event);
        bo.setSource(LogSrcEnum.PC);
        bo.setModule(module);
        bo.setTitle(title);
        bo.setContent(content);
        bo.setType(LogTypeEnum.ONE.getKey());
        bo.setIsSuccess(isSuccess);
        boolean flag = sysLogService.add(bo, "admin");
        return flag;
    }

    /**
     * 货值最新一条货值版本
     * @param projectFid 分期id
     * @return PriceNewestVersion
     */
    @Override
    public PriceNewestVersion priceNewestVersion(String projectFid) {
        return priceValueOrgMapper.priceNewestVersion(projectFid, IsDeleteEnum.NO.getKey());
    }

    /**
     * 全盘货值概览-查询概览数据
     */
    @Override
    public PriceValueOrg selectViewDataById(String id) {
        return priceValueOrgMapper.selectDataById(id);
    }

    /**
     * 查询分期下版本类型和版本状态和是否删除的货值版本
     * @param projectFid 分期id
     * @param existVersionTypes 版本类型
     * @param existVersionStates 版本状态
     * @param isDel 是否删除
     * @return List<PriceVersion>
     */
    @Override
    public List<PriceVersion> selectApprovalVersionByFidAndTypesAndStates(String projectFid, List<String> existVersionTypes, List<String> existVersionStates, int isDel) {
        List<PriceVersion> priceOtherVersions = priceVersionMapper.selectApprovalVersionByFidAndTypesAndStates(projectFid, existVersionTypes, existVersionStates, IsDeleteEnum.NO.getKey());
        if (CollectionUtils.isNotEmpty(priceOtherVersions)) {
            throw new MsgException(CodeEnum.EXIST_APPROVAL_CASTDECISION_VERSIONS);
        }

        return priceOtherVersions;
    }

    /**
     * 查询分期下版本类型和版本状态为（审批通过、系统生成）的未删除货值版本
     * @param projectFid 分期id
     * @param versionType 版本类型
     * @return PriceVersion
     */
    @Override
    public PriceVersion selectNewestVersionByFid(String projectFid, String versionType) {
        return priceVersionMapper.selectNewestVersionByFid(projectFid, versionType, Arrays.asList(VersionStatusEnum.SUCCESSAPPROVED.getKey(), VersionStatusEnum.SYSGENERATION.getKey()), IsDeleteEnum.NO.getKey());
    }

    /**
     *  货值保存层级信息
     * @param newVersion 保存的货值版本
     * @param groupInsertList 组团层级
     * @param productInsertList 业态层级
     * @param buildInsertList 楼栋层级
     * @param hoseSoleList 房源层级
     * @param parkSoleList 车位层级
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveInfo(PriceVersion newVersion, List<PriceValueOrg> projectFList, List<PriceValueOrg> groupInsertList, List<PriceValueOrg> productInsertList, List<PriceValueOrg> buildInsertList, List<PriceValueOrg> hoseSoleList, List<PriceValueOrg> parkSoleList) {
        //测试保存
        priceVersionMapper.insertRecord(newVersion);
        priceValueOrgMapper.insertBatch(projectFList);
        if (CollectionUtils.isNotEmpty(groupInsertList)) {
            priceValueOrgMapper.insertBatch(groupInsertList);
        }
        if (CollectionUtils.isNotEmpty(productInsertList)) {
            priceValueOrgMapper.insertBatch(productInsertList);
        }
        if (CollectionUtils.isNotEmpty(buildInsertList)) {
            priceValueOrgMapper.insertBatch(buildInsertList);
        }
        if (CollectionUtils.isNotEmpty(hoseSoleList)) {
            priceValueOrgMapper.insertBatch(hoseSoleList);
        }
        if (CollectionUtils.isNotEmpty(parkSoleList)) {
            priceValueOrgMapper.insertBatch(parkSoleList);
        }

    }

    /**
     * 货值版本对比
     * @param projectId 分期id
     * @param versionTypes 货值版本类型
     * @return PriceCompareBasicInfoVO
     */
    @Override
    public List<PriceCompareBasicInfoVO> priceVersionCompareBasic(String projectId, List<String> versionTypes) {
        List<MdmStage> stageList = stageService.selectByProjectId(projectId, IsDeleteEnum.NO.getKey());
        if (CollectionUtils.isEmpty(stageList)){
            throw new MsgException(CodeEnum.NOTICE_NON_EXISTENT);
        }

        List<PriceCompareBasicInfoVO> infoVOList = new ArrayList<PriceCompareBasicInfoVO>();

        if (CollectionUtils.isNotEmpty(stageList)) {
            priceVersionCompareBasicByStageInfo(versionTypes, stageList, infoVOList);
        }

        return infoVOList;
    }

    private void priceVersionCompareBasicByStageInfo(List<String> versionTypes, List<MdmStage> stageList, List<PriceCompareBasicInfoVO> infoVOList) {
        wc : for (MdmStage stage : stageList) {

            PriceCompareBasicInfoVO basicInfoVO = new PriceCompareBasicInfoVO();
            basicInfoVO.setStageId(stage.getProjectFid());
            basicInfoVO.setStageName(stage.getStageName());

            List<PriceVersionListVO> orgList = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(versionTypes)) {
                priceVersionCompareBasicByStageInfoToVersionType(versionTypes, stage, basicInfoVO, orgList);
            } else {
                if (priceVersionCompareBasicByStageInfoToNews(stage, basicInfoVO, orgList)) continue wc;
            }

            if(basicInfoVO.getItemInfo() != null){
                infoVOList.add(basicInfoVO);
            }
        }
    }

    private boolean priceVersionCompareBasicByStageInfoToNews(MdmStage stage, PriceCompareBasicInfoVO basicInfoVO, List<PriceVersionListVO> orgList) {
        //查询全盘货值
        //全盘货值中去除禁用分期
        String status = stage.getStatus();
        if (StringUtils.isNotEmpty(status) && status.equals(StageStatusEnum.INACTIVE.getKey())){
            return true;
        }

        //先查询是否有明源已售或者已定价得版本
        PriceVersion priceVersion = getNewestPriceVersion(stage.getProjectFid());

        if(priceVersion != null){
            PriceVersionListVO priceVersionListVO = new PriceVersionListVO();
            setVersionInfo(priceVersion, priceVersionListVO);
            orgList.add(priceVersionListVO);
            basicInfoVO.setItemInfo(orgList);
        }
        return false;
    }

    private void priceVersionCompareBasicByStageInfoToVersionType(List<String> versionTypes, MdmStage stage, PriceCompareBasicInfoVO basicInfoVO, List<PriceVersionListVO> orgList) {
        //查询分期对应版本阶段
        List<PriceVersion> priceVersions = priceVersionMapper.selectApprovalVersionByFidAndTypesAndStates(stage.getProjectFid(), versionTypes, Arrays.asList(VersionStatusEnum.SUCCESSAPPROVED.getKey(), VersionStatusEnum.SYSGENERATION.getKey()), IsDeleteEnum.NO.getKey());
        if (CollectionUtils.isNotEmpty(priceVersions)){

            for (PriceVersion priceVersion : priceVersions){
                PriceVersionListVO priceVersionListVO = new PriceVersionListVO();
                setVersionInfo(priceVersion, priceVersionListVO);

                orgList.add(priceVersionListVO);
            }

            basicInfoVO.setItemInfo(orgList);
        }
    }

    /**
     * 货值版本列表信息赋值
     * @param priceVersion 货值版本
     * @param priceVersionListVO
     */
    private void setVersionInfo(PriceVersion priceVersion, PriceVersionListVO priceVersionListVO) {
    	priceVersionListVO.setBatchAdjust(priceVersion.getBatchAdjust());
    	priceVersionListVO.setVersionId(priceVersion.getId());
        priceVersionListVO.setVersionName(priceVersion.getVersionName());
        priceVersionListVO.setVersionType(VersionTypeEunm.getValueByKey(priceVersion.getVersionType()));
        priceVersionListVO.setVersionTypeCode(priceVersion.getVersionType());
        priceVersionListVO.setVersionNum(priceVersion.getVersionNum());
        priceVersionListVO.setVersionStateCode(priceVersion.getVersionState());
        priceVersionListVO.setVersionState(VersionStatusEnum.getValueByKey(priceVersion.getVersionState()));
        priceVersionListVO.setIsMarket(priceVersion.getIsMarket());
        priceVersionListVO.setVersionBuildSource(priceVersion.getSourcePlanDetail());
        priceVersionListVO.setVersionAreaSource(priceVersion.getSourceAreaDetail());
        priceVersionListVO.setIsAssessmentVersion(priceVersion.getIsAssessmentVersion());
        priceVersionListVO.setVersionAscriptionDate(priceVersion.getAscriptionDate());

        //查询创建人
        if (StringUtils.isNotEmpty(priceVersion.getCreateBy())) {
            if (!priceVersion.getCreateBy().equals(Constants.SYS)) {
                IdmUser idmUser = idmUserService.getByAlias(priceVersion.getCreateBy());
                if(idmUser != null){
                    priceVersionListVO.setCreateUser(idmUser.getUsercn());
                }
            } else {
                priceVersionListVO.setCreateUser("系统创建");
            }
        }
        priceVersionListVO.setCreateTime(priceVersion.getCreateTime());
        priceVersionListVO.setCreateMethodCode(priceVersion.getVersionCreateState());
        priceVersionListVO.setCreateMethod(VersionCreateEnum.getKeyByValue(priceVersion.getVersionCreateState()));
        priceVersionListVO.setUpdateTime(priceVersion.getUpdateTime());
        priceVersionListVO.setVersionLable(priceVersion.getVersionLable());

        //查看该分期是否存在大定价版
        List<PriceVersion> priceExistWPVersions = priceVersionMapper.selectApprovalVersionByFidAndTypesAndStates(priceVersion.getProjectfId(),
                Arrays.asList(VersionTypeEunm.GETPRICE.getKey()),
                Arrays.asList(VersionStatusEnum.NOTPREPARED.getKey(), VersionStatusEnum.ORGANIZATION.getKey(), VersionStatusEnum.EXAMINEDAPPROVED.getKey(), VersionStatusEnum.APPROVED.getKey(), VersionStatusEnum.FAILUREAPPROVED.getKey(), VersionStatusEnum.SUCCESSAPPROVED.getKey()), IsDeleteEnum.NO.getKey());
        if (CollectionUtils.isNotEmpty(priceExistWPVersions)) {
            priceVersionListVO.setVersionAccountStage(VersionTypeEunm.GETPRICE.getKey());
        } else {
            priceVersionListVO.setVersionAccountStage(VersionTypeEunm.WARPLAN.getKey());
        }

        priceVersionListVO.setSourceAreaVersionStage(priceVersion.getSourceAreaVersionStage());
        priceVersionListVO.setSourceAreaVersionCode(priceVersion.getSourceAreaVersionNum());
        priceVersionListVO.setSourceAreaVersionTime(priceVersion.getSourceAreaCreatedTime());
        priceVersionListVO.setSourcePanoVersionStage(priceVersion.getSourcePanoVersionType());
        priceVersionListVO.setSourcePanoVersionCode(priceVersion.getSourcePanoPlanVersion());
        priceVersionListVO.setSourcePanoVersionTime(priceVersion.getSourcePanoCreatedDate());
    }

    /**
     *  货值全盘最新
     * @param projectFId 分期id
     * @return PriceVersion
     */
    @Override
    public PriceVersion getNewestPriceVersion(String projectFId) {
        PriceVersion version = priceVersionMapper.selectSaleValue(projectFId, IsDeleteEnum.NO.getKey());
        if (version == null) {
            //如果没有一房一价,那就取动态版,大定价,战规中最新的
            version = priceVersionMapper.selectNewestVersionByFidAndTypes(projectFId, Arrays.asList(VersionTypeEunm.DYNAMIC.getKey(), VersionTypeEunm.GETPRICE.getKey(), VersionTypeEunm.WARPLAN.getKey()), Arrays.asList(VersionStatusEnum.SUCCESSAPPROVED.getKey(), VersionStatusEnum.SYSGENERATION.getKey()), IsDeleteEnum.NO.getKey());
            if (version == null) {
                //没有战规后版本就取投资版
                version = priceVersionMapper.selectCastDecisionNewestVersionByFid(projectFId, Arrays.asList(VersionStatusEnum.SUCCESSAPPROVED.getKey(), VersionStatusEnum.SYSGENERATION.getKey()), IsDeleteEnum.NO.getKey());
            }
        }else{
            //如果有一房一价,那就取动态版,大定价最新的
            version = priceVersionMapper.selectNewestVersionByFidAndTypes(projectFId, Arrays.asList(VersionTypeEunm.DYNAMIC.getKey(), VersionTypeEunm.GETPRICE.getKey()), Arrays.asList(VersionStatusEnum.SUCCESSAPPROVED.getKey(), VersionStatusEnum.SYSGENERATION.getKey()), IsDeleteEnum.NO.getKey());
        }
        return version;
    }

    /**
     * 查询分期下全状态的全盘最新版本
     */
    @Override
    public PriceVersion getNewestPriceVersionAllVersionState(String projectFId) {
        PriceVersion version = priceVersionMapper.selectSaleValue(projectFId, IsDeleteEnum.NO.getKey());
        if (version == null) {
            //如果没有一房一价,那就取动态版,大定价,战规中最新的
            version = priceVersionMapper.selectNewestVersionByFidAndTypes(projectFId, Arrays.asList(VersionTypeEunm.DYNAMIC.getKey(), VersionTypeEunm.GETPRICE.getKey(), VersionTypeEunm.WARPLAN.getKey()),
                    Arrays.asList(VersionStatusEnum.NOTPREPARED.getKey(), VersionStatusEnum.ORGANIZATION.getKey(), VersionStatusEnum.EXAMINEDAPPROVED.getKey(), VersionStatusEnum.APPROVED.getKey(),
                            VersionStatusEnum.FAILUREAPPROVED.getKey(), VersionStatusEnum.SUCCESSAPPROVED.getKey(), VersionStatusEnum.SYSGENERATION.getKey()),
                    IsDeleteEnum.NO.getKey());
            if (version == null) {
                //没有战规后版本就取投资版
                version = priceVersionMapper.selectCastDecisionNewestVersionByFid(projectFId, Arrays.asList(VersionStatusEnum.NOTPREPARED.getKey(), VersionStatusEnum.ORGANIZATION.getKey(), VersionStatusEnum.EXAMINEDAPPROVED.getKey(), VersionStatusEnum.APPROVED.getKey(),
                        VersionStatusEnum.FAILUREAPPROVED.getKey(), VersionStatusEnum.SUCCESSAPPROVED.getKey(), VersionStatusEnum.SYSGENERATION.getKey()),
                        IsDeleteEnum.NO.getKey());
            }
        }else{
            //如果有一房一价,那就取动态版,大定价最新的
            version = priceVersionMapper.selectNewestVersionByFidAndTypes(projectFId, Arrays.asList(VersionTypeEunm.DYNAMIC.getKey(), VersionTypeEunm.GETPRICE.getKey()),
                    Arrays.asList(VersionStatusEnum.NOTPREPARED.getKey(), VersionStatusEnum.ORGANIZATION.getKey(), VersionStatusEnum.EXAMINEDAPPROVED.getKey(), VersionStatusEnum.APPROVED.getKey(),
                            VersionStatusEnum.FAILUREAPPROVED.getKey(), VersionStatusEnum.SUCCESSAPPROVED.getKey(), VersionStatusEnum.SYSGENERATION.getKey()), IsDeleteEnum.NO.getKey());
        }
        return version;
    }

    /**
     *  查询指定货值版本
     * @param versionId 货值id
     * @return PriceVersion
     */
    @Override
    public PriceVersion selectByVersionId(String versionId) {
        return priceVersionMapper.selectByVersionId(versionId,IsDeleteEnum.NO.getKey());
    }

    /**
     *  货值版本对比
     * @param priceCompareVersionIdsVOs 主、从版本ids
     * @return ApprovedDiffDetailVO
     */
    @Override
    public List<ApprovedDiffDetailVO> priceVersionCompare(List<PriceCompareVersionIdsVO> priceCompareVersionIdsVOs) {
        List<ApprovedDiffDetailVO> approvedDiffDetail = new ArrayList<>();

        String projectId = null;

        if (CollectionUtils.isNotEmpty(priceCompareVersionIdsVOs)){
            for (PriceCompareVersionIdsVO priceCompareVersionIdsVO : priceCompareVersionIdsVOs){
                String masterVersionId = priceCompareVersionIdsVO.getMasterVersionId();
                ApprovalVersionCompare afterVersionCompare = null;
                PriceVersion masterPriceVersion = null;
                if(StringUtils.isNotEmpty(masterVersionId)){
                    masterPriceVersion = priceVersionMapper.selectByPrimaryKey(masterVersionId);
                    afterVersionCompare = new ApprovalVersionCompare();
                    afterVersionCompare.setVersionIdCompare(masterVersionId);
                    afterVersionCompare.setVersionTypeCompare(masterPriceVersion.getVersionType());
                    afterVersionCompare.setVersionNumCompare(masterPriceVersion.getVersionNum());
                    afterVersionCompare.setStageId(masterPriceVersion.getProjectfId());
                }

                String slaveVersionId = priceCompareVersionIdsVO.getSlaveVersionId();
                ApprovalVersionCompare slaveVersionCompare = null;
                PriceVersion slavePriceVersion = null;
                if (StringUtils.isNotEmpty(slaveVersionId)){
                    slavePriceVersion = priceVersionMapper.selectByPrimaryKey(slaveVersionId);
                    slaveVersionCompare = new ApprovalVersionCompare();
                    slaveVersionCompare.setVersionIdCompare(slaveVersionId);
                    slaveVersionCompare.setVersionTypeCompare(slavePriceVersion.getVersionType());
                    slaveVersionCompare.setVersionNumCompare(slavePriceVersion.getVersionNum());
                    slaveVersionCompare.setStageId(slavePriceVersion.getProjectfId());
                }

                if (afterVersionCompare == null){
                    afterVersionCompare = slaveVersionCompare;
                }
                List<ApprovedDiffDetailVO> approvedDiffDetailVOS = submitApprovedProjectServiceImpl.mergeDataList(afterVersionCompare, slaveVersionCompare , null, false);
                approvedDiffDetail.addAll(approvedDiffDetailVOS);

                if (masterPriceVersion != null){
                    projectId = masterPriceVersion.getProjectId();
                }else if(slavePriceVersion != null){
                    projectId = slavePriceVersion.getProjectId();
                }
            }

            try{
                submitApprovedProjectServiceImpl.pricerVersionCompareInfo(projectId, OrgTypeEunm.ORG_PRODUCTF.getKey(), approvedDiffDetail);
            }catch (Exception e){
                logger.error("#################      priceVersionCompare    error:"+e.getMessage(), e);
            }
        }

        return submitApprovedProjectServiceImpl.stageSort(approvedDiffDetail);
    }

    /**
     * 方法描述：将double转成BigDecimal向减
     * @param money 被减数
     * @param price 减数
     * 创建人：yang
     * 创建时间：2017年3月15日 下午3:13:03
     */
    public BigDecimal BigDecimalSUB(BigDecimal money, BigDecimal price) {
        if (money != null && price != null){
            return money.subtract(price).setScale(4, BigDecimal.ROUND_HALF_UP);
        }else if (money != null && null == price){
            return money;
        }else if (null == money && price != null){
            return price;
        }else {
            return new BigDecimal(0);
        }
    }

    /**
     * 方法描述：将double转成BigDecimal向加
     * @param money 被加数
     * @param price 加数
     * 创建人：yang
     * 创建时间：2017年3月15日 下午3:13:03
     */
    public static BigDecimal BigDecimalADD(BigDecimal money, BigDecimal price) {

        if(money != null && price != null){
            BigDecimal b1 = money.setScale(4, BigDecimal.ROUND_HALF_UP);
            BigDecimal b2 = price.setScale(4, BigDecimal.ROUND_HALF_UP);
            BigDecimal doubleValue = b1.add(b2).setScale(4, BigDecimal.ROUND_HALF_UP);
            return doubleValue;
        }else if(null == money && null == price){
            return new BigDecimal(0);
        }else if (money != null && null == price){
            return money;
        }else{
            return price;
        }
    }

    /**
     *  货值版本校验
     * @param versionId 版本id
     * @return 是否验证成功
     */
    @Override
    public String priceVersionValidated(String versionId) {
        String result = "";
        PriceVersion priceVersion = priceVersionMapper.selectByPrimaryKey(versionId);
        if (priceVersion != null){
            String versionType = priceVersion.getVersionType();
            if (versionType.equals(VersionTypeEunm.INVESTMENT.getKey())) {
                return investmentValidatedInfo(versionId, result);
            } else {
                return dynamicValidatedInfo(versionId, result, priceVersion);
            }
        }else{
            throw new MsgException(CodeEnum.NON_EXISTENT_VERSIONS_ORG);
        }
    }

    private String dynamicValidatedInfo(String versionId, String result, PriceVersion priceVersion) {
        String isMarket = priceVersion.getIsMarket();

        //校验
        Map<String, List<PriceValueOrg>> otherMap = new HashMap<String, List<PriceValueOrg>>();
        QueryWrapper<PriceValueOrg> otherWrapper = new QueryWrapper<PriceValueOrg>();
        otherWrapper.eq("version_id", versionId)
                .in("type", OrgTypeEunm.ORG_HOUSE_PACKAGE.getKey(), OrgTypeEunm.ORG_SALE_PACKAGE.getKey(),
                        OrgTypeEunm.ORG_NOT_SALE_PACKAGE.getKey(), OrgTypeEunm.ORG_SALING_PARKING.getKey(), OrgTypeEunm.ORG_NOT_SALING_PARKING.getKey())
                .eq("is_delete", IsDeleteEnum.NO.getKey());
        List<PriceValueOrg> otherOrgs = priceValueOrgMapper.selectList(otherWrapper);
        for (PriceValueOrg otherOrg : otherOrgs) {
            String x = dynamicOtherOrgsValidatedInfo(isMarket, otherMap, otherOrg);
            if (x != null) return x;
        }

        QueryWrapper<PriceValueOrg> buildWrapper = new QueryWrapper<PriceValueOrg>();
        buildWrapper.eq("version_id", versionId)
                .eq("type", OrgTypeEunm.ORG_BUILD.getKey())
                .eq("is_delete", IsDeleteEnum.NO.getKey());
        List<PriceValueOrg> buildOrgs = priceValueOrgMapper.selectList(buildWrapper);
        for (PriceValueOrg buildOrg : buildOrgs) {
            if(buildOrg.getBusinessType().equals(SalyTypeEnum.RENTED.getKey())
                    || buildOrg.getBusinessType().equals(SalyTypeEnum.NOT_RENTABLE.getKey()) ){
                continue;
            }

            String x = dynamicBuildOrgsValidatedInfo(isMarket, otherMap, buildOrg);
            if (x != null) return x;
        }

        return result;
    }

    private String dynamicBuildOrgsValidatedInfo(String isMarket, Map<String, List<PriceValueOrg>> otherMap, PriceValueOrg buildOrg) {
        Integer isParking = buildOrg.getIsParking();
        if (isParking.equals(IsDeleteEnum.YES.getKey())) {
            String x = dynamicBuildOrgsParkingValidatedInfo(otherMap, buildOrg);
            if (x != null) return x;
        } else {
            String x = dynamicBuildOrgsHouseValidatedInfo(isMarket, otherMap, buildOrg);
            if (x != null) return x;
        }
        return null;
    }

    private String dynamicBuildOrgsHouseValidatedInfo(String isMarket, Map<String, List<PriceValueOrg>> otherMap, PriceValueOrg buildOrg) {
        if(buildOrg.getIsTotalCollect() == null || buildOrg.getIsTotalCollect().equals(0)){
            BigDecimal averagePriceHouse = buildOrg.getAveragePriceHouse();
            if (averagePriceHouse == null || averagePriceHouse.compareTo(new BigDecimal(0)) == 0){
                return buildOrg.getOrgName()+"：均价不能为空";
            }

            BigDecimal buildSaleArea = buildOrg.getSaleArea();
            Integer buildRoomNum = buildOrg.getRoomNum();

            List<PriceValueOrg> valueOrgs = otherMap.get(buildOrg.getId());
            if (CollectionUtils.isNotEmpty(valueOrgs)){
                Integer sumNum = 0;
                BigDecimal sumArea = new BigDecimal(0);
                for (PriceValueOrg valueOrg : valueOrgs){
                    sumNum = sumNum + (valueOrg.getRoomNum()==null?0:valueOrg.getRoomNum());
                    sumArea = BigDecimalADD(sumArea, valueOrg.getSaleArea());
                }

                if (buildRoomNum != null && buildRoomNum != 0 && !sumNum.equals(buildRoomNum)){
                    return buildOrg.getOrgName()+"：请完成拆分套数";
                }

                if (buildSaleArea != null && buildSaleArea.compareTo(new BigDecimal(0)) != 0 && sumArea.compareTo(buildSaleArea) != 0){
                    return buildOrg.getOrgName()+"：请完成拆分面积";
                }
            }else{
                if (isMarket.equals(MarketingEunm.IS_MARKET.getKey())){
                    return buildOrg.getOrgName()+"：请完成拆分楼栋下面积段";
                }
            }
        }
        return null;
    }

    private String dynamicBuildOrgsParkingValidatedInfo(Map<String, List<PriceValueOrg>> otherMap, PriceValueOrg buildOrg) {
        String id = buildOrg.getId();
        Integer parkingNum = buildOrg.getParkingNum();
        Integer forsaleParkingNum = buildOrg.getForsaleParkingNum();
        if(parkingNum == null || forsaleParkingNum == null || (parkingNum.equals(0) && forsaleParkingNum.equals(0))){
            return buildOrg.getOrgName()+"：套数不能为空";
        }

        BigDecimal averagePriceParking = buildOrg.getAveragePriceParking();
        if (parkingNum != null && !parkingNum.equals(0)){
            if (averagePriceParking == null || averagePriceParking.compareTo(new BigDecimal(0)) == 0){
                return buildOrg.getOrgName()+"：均价不能为空";
            }
        }

        List<PriceValueOrg> orgList = otherMap.get(id);
        if(CollectionUtils.isNotEmpty(orgList)){
            Integer collectParkingNum = 0;
            for (PriceValueOrg otherOrg : orgList) {
                if (otherOrg.getType().equals(OrgTypeEunm.ORG_NOT_SALING_PARKING.getKey())) {
                    Integer otherForsaleParkingNum = otherOrg.getForsaleParkingNum();
                    if (forsaleParkingNum == null || otherForsaleParkingNum == null || !otherForsaleParkingNum.equals(forsaleParkingNum)){
                        return buildOrg.getOrgName()+"：楼栋的未推售数量和楼栋下的未推售数量不一致";
                    }
                } else {
                    Integer otherParkingNum = otherOrg.getParkingNum()==null?0:otherOrg.getParkingNum();
                    collectParkingNum = collectParkingNum + otherParkingNum;
                }
            }

            if (collectParkingNum == null || parkingNum == null || !parkingNum.equals(collectParkingNum)){
                return buildOrg.getOrgName()+"：楼栋的可售数量和楼栋下的可售数量不一致";
            }
        }
        return null;
    }

    private String dynamicOtherOrgsValidatedInfo(String isMarket, Map<String, List<PriceValueOrg>> otherMap, PriceValueOrg otherOrg) {
        String pid = otherOrg.getPid();
        String type = otherOrg.getType();
        Integer isSplit = otherOrg.getIsSplit();
        if (type.equals(OrgTypeEunm.ORG_HOUSE_PACKAGE.getKey())){

            if (isMarket.equals(MarketingEunm.IS_MARKET.getKey())){
                if (otherOrg.getOrgName().equals(Constants.ORTHER_HOUSE_NAME)){
                    return otherOrg.getOrgName()+"：营销操盘请拆分完成‘其它’面积段";
                }
            }

            if(isSplit == null || isSplit.equals(0)){
                BigDecimal averagePriceHouse = otherOrg.getAveragePriceHouse();
                if (averagePriceHouse == null || averagePriceHouse.compareTo(new BigDecimal(0)) == 0){
                    return otherOrg.getOrgName()+"：均价不能为空";
                }
            }
        }else{
            if(!otherOrg.getType().equals(OrgTypeEunm.ORG_NOT_SALING_PARKING.getKey())){
                Integer parkingNum = otherOrg.getParkingNum();
                BigDecimal averagePriceParking = otherOrg.getAveragePriceParking();
                if(parkingNum != null && !parkingNum.equals(0)){
                    if (averagePriceParking == null || averagePriceParking.compareTo(new BigDecimal(0)) == 0){
                        return otherOrg.getOrgName()+"：均价不能为空";
                    }
                }
            }
        }

        List<PriceValueOrg> valueOrgs = otherMap.get(pid);
        if (CollectionUtils.isEmpty(valueOrgs)){
            valueOrgs = new ArrayList<>();
        }
        valueOrgs.add(otherOrg);
        otherMap.put(pid, valueOrgs);
        return null;
    }

    private String investmentValidatedInfo(String versionId, String result) {
        Map<String, List<PriceValueOrg>> otherMap = new HashMap<String, List<PriceValueOrg>>();
        QueryWrapper<PriceValueOrg> otherWrapper = new QueryWrapper<PriceValueOrg>();
        otherWrapper.eq("version_id", versionId)
                .in("type", OrgTypeEunm.ORG_SALE_PACKAGE.getKey(),OrgTypeEunm.ORG_NOT_SALE_PACKAGE.getKey(),
                        OrgTypeEunm.ORG_SALING_PARKING.getKey(),OrgTypeEunm.ORG_NOT_SALING_PARKING.getKey())
                .eq("is_delete", IsDeleteEnum.NO.getKey());
        List<PriceValueOrg> otherOrgs = priceValueOrgMapper.selectList(otherWrapper);
        if(CollectionUtils.isNotEmpty(otherOrgs)){
            for (PriceValueOrg otherOrg : otherOrgs) {
                if (investmentOtherOrgsValidatedInfo(otherMap, otherOrg)) return otherOrg.getOrgName() + "：均价不能为空";
            }
        }

        QueryWrapper<PriceValueOrg> productWrapper = new QueryWrapper<PriceValueOrg>();
        productWrapper.eq("version_id", versionId)
                .eq("type", OrgTypeEunm.ORG_PRODUCT.getKey())
                .in("business_type", Arrays.asList(SalyTypeEnum.SALABLE.getKey(),SalyTypeEnum.STAGE_SELF_SUSTAINMENT.getKey()))
                .eq("is_delete", IsDeleteEnum.NO.getKey());
        List<PriceValueOrg> productOrgs = priceValueOrgMapper.selectList(productWrapper);
        for (PriceValueOrg productOrg : productOrgs) {
            String x = investmentProductOrgsValidatedInfo(otherMap, productOrg);
            if (x != null) return x;
        }

        return result;
    }

    private String investmentProductOrgsValidatedInfo(Map<String, List<PriceValueOrg>> otherMap, PriceValueOrg productOrg) {
        if (isParkList.contains(productOrg.getProductCode())){
            Integer parkingNum = productOrg.getParkingNum();
            Integer forsaleParkingNum = productOrg.getForsaleParkingNum();
            if(parkingNum == null || forsaleParkingNum == null || (parkingNum.equals(0) && forsaleParkingNum.equals(0))){
                return productOrg.getOrgName()+"：套数不能为空";
            }

            if(parkingNum != null && !parkingNum.equals(0)){
                BigDecimal averagePriceParking = productOrg.getAveragePriceParking();
                if (averagePriceParking == null || averagePriceParking.compareTo(new BigDecimal(0)) == 0){
                    return productOrg.getOrgName()+"：均价不能为空";
                }
            }
        }else{
            BigDecimal averagePriceHouse = productOrg.getAveragePriceHouse();
            if (averagePriceHouse == null || averagePriceHouse.compareTo(new BigDecimal(0)) == 0){
                return productOrg.getOrgName()+"：均价不能为空";
            }

            Integer roomNum = productOrg.getRoomNum();
            if(roomNum == null || roomNum.equals(0)){
                return productOrg.getOrgName()+"：套数不能为空";
            }

            BigDecimal saleArea = productOrg.getSaleArea();
            if (saleArea == null || saleArea.compareTo(new BigDecimal(0)) == 0){
                return productOrg.getOrgName()+"：面积不能为空";
            }
        }

        List<PriceValueOrg> orgList = otherMap.get(productOrg);
        if(CollectionUtils.isNotEmpty(orgList)){
            Integer collectParkingNum = 0;
            Integer collectForsaleParkingNum = 0;
            for (PriceValueOrg otherOrg : orgList){
                if (otherOrg.getType().equals(OrgTypeEunm.ORG_NOT_SALING_PARKING.getKey())){
                    Integer forsaleParkingNum = otherOrg.getForsaleParkingNum()==null?0:otherOrg.getForsaleParkingNum();
                    collectForsaleParkingNum = collectForsaleParkingNum + forsaleParkingNum;
                }else{
                    Integer parkingNum = otherOrg.getParkingNum()==null?0:otherOrg.getParkingNum();
                    collectParkingNum = collectParkingNum + parkingNum;
                }
            }

            Integer parkingNum = productOrg.getParkingNum()==null?0:productOrg.getParkingNum();
            Integer forsaleParkingNum = productOrg.getForsaleParkingNum()==null?0:productOrg.getForsaleParkingNum();
            if (!parkingNum.equals(collectParkingNum)){
                return productOrg.getOrgName()+"：产品构成下可售车位数量和产品构成可售车位数量不一致";
            }

            if (!forsaleParkingNum.equals(collectForsaleParkingNum)){
                return productOrg.getOrgName()+"：产品构成下未推售车位数量和产品构成未推售车位数量不一致";
            }
        }
       return null;
    }

    private boolean investmentOtherOrgsValidatedInfo(Map<String, List<PriceValueOrg>> otherMap, PriceValueOrg otherOrg) {
        if(!otherOrg.getType().equals(OrgTypeEunm.ORG_NOT_SALING_PARKING.getKey())){
            Integer parkingNum = otherOrg.getParkingNum();
            BigDecimal averagePriceParking = otherOrg.getAveragePriceParking();
            if(parkingNum != null && !parkingNum.equals(0)){
                if (averagePriceParking == null || averagePriceParking.compareTo(new BigDecimal(0)) == 0){
                    return true;
                }
            }
        }

        List<PriceValueOrg> orgList = otherMap.get(otherOrg.getPid());
        if(CollectionUtils.isEmpty(orgList)){
            orgList = new ArrayList<PriceValueOrg>();
        }
        orgList.add(otherOrg);
        otherMap.put(otherOrg.getPid(), orgList);
        return false;
    }

    /**
     *  货值版本详情
     * @param versionId 版本id
     * @return PriceVersionListVO
     */
    @Override
    public PriceVersionListVO priceVersionDetail(String versionId) {
        PriceVersionListVO priceVersionListVO = new PriceVersionListVO();
        PriceVersion priceVersion = priceVersionMapper.selectByPrimaryKey(versionId);
        if (priceVersion != null){

            getPriceVersionListVoInfo(versionId, priceVersionListVO, priceVersion);
        }else{
            throw new MsgException(CodeEnum.STAGE_NON_EXISTENT);
        }

        return priceVersionListVO;
    }

    /**
     * priceVersionListVO赋值
     */
    private void getPriceVersionListVoInfo(String versionId, PriceVersionListVO priceVersionListVO, PriceVersion priceVersion) {
        priceVersionListVO.setVersionId(versionId);
        priceVersionListVO.setVersionName(priceVersion.getVersionName());
        priceVersionListVO.setVersionType(VersionTypeEunm.getValueByKey(priceVersion.getVersionType()));
        priceVersionListVO.setVersionTypeCode(priceVersion.getVersionType());
        priceVersionListVO.setVersionNum(priceVersion.getVersionNum());
        priceVersionListVO.setVersionStateCode(priceVersion.getVersionState());
        priceVersionListVO.setVersionState(VersionStatusEnum.getValueByKey(priceVersion.getVersionState()));
        priceVersionListVO.setIsMarket(priceVersion.getIsMarket());
        priceVersionListVO.setVersionBuildSource(priceVersion.getSourcePlanDetail());
        priceVersionListVO.setVersionAreaSource(priceVersion.getSourceAreaDetail());
        priceVersionListVO.setIsAssessmentVersion(priceVersion.getIsAssessmentVersion());

        //查询创建人
        IdmUser idmUser = idmUserService.getByAlias(priceVersion.getCreateBy());
        if(idmUser != null){
            priceVersionListVO.setCreateUser(idmUser.getUsercn());
        }
        priceVersionListVO.setCreateTime(priceVersion.getCreateTime());
        priceVersionListVO.setCreateMethodCode(priceVersion.getVersionCreateState());
        priceVersionListVO.setCreateMethod(VersionCreateEnum.getKeyByValue(priceVersion.getVersionCreateState()));
        priceVersionListVO.setUpdateTime(priceVersion.getUpdateTime());
        priceVersionListVO.setVersionLable(priceVersion.getVersionLable());

        //查看该分期是否存在大定价版
        List<PriceVersion> priceExistWPVersions = priceVersionMapper.selectApprovalVersionByFidAndTypesAndStates(priceVersion.getProjectfId(), Arrays.asList(VersionTypeEunm.GETPRICE.getKey()), Arrays.asList(VersionStatusEnum.SUCCESSAPPROVED.getKey()), IsDeleteEnum.NO.getKey());
        if (CollectionUtils.isNotEmpty(priceExistWPVersions)){
            priceVersionListVO.setVersionAccountStage(VersionTypeEunm.GETPRICE.getKey());
        }else{
            priceVersionListVO.setVersionAccountStage(VersionTypeEunm.WARPLAN.getKey());
        }
    }

    /**
     *  货值版本设置标签
     * @param versionId 版本id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void priceVersionAssessmentLable(String versionId) {

        PriceVersion priceVersion = priceVersionMapper.selectByPrimaryKey(versionId);
        if (priceVersion != null){

            String versionType = priceVersion.getVersionType();
            if (StringUtils.isNotEmpty(versionType) && versionType.equals(VersionTypeEunm.INVESTMENT.getKey())){

                String versionState = priceVersion.getVersionState();
                if(StringUtils.isNotEmpty(versionState) &&
                        (versionState.equals(VersionStatusEnum.SUCCESSAPPROVED.getKey()) || versionState.equals(VersionStatusEnum.SYSGENERATION.getKey()))){
                    priceVersionMapper.updateAssessmentLable(IsDeleteEnum.NO.getKey() ,priceVersion.getProjectfId(), versionType);

                    priceVersion.setIsAssessmentVersion(IsDeleteEnum.YES.getKey());
                    priceVersionMapper.updateByPrimaryKeySelective(priceVersion);

                    try{
                        //修改供货计划考核标签
                        supplyPlanVersionService.updateAssessmentTag(priceVersion.getId(),priceVersion.getProjectfId());
                    }catch (Exception e) {
                        logger.error("#############      priceVersionAssessmentLable  error:"+e.getMessage(), e);
                    }
                }else{
                    throw new MsgException(CodeEnum.NON_ASSESSMENT_VERSION);
                }
            }else{
                throw new MsgException(CodeEnum.NON_ASSESSMENT_VERSIONS);
            }
        }else{
            throw new MsgException(CodeEnum.NON_EXISTENT_VERSIONS_ORG);
        }
    }

    /**
     * 查询货值指定归属日期和分期
     * @param projectFid 分期id
     * @param versionTypes 货值类型
     * @param versionStates 货值状态
     * @param isDel 是否删除
     * @param now 归属日期
     * @return PriceVersion
     */
    @Override
    public PriceVersion selectNewestVersionByFidAndDate(String projectFid, List<String> versionTypes, List<String> versionStates, int isDel, LocalDateTime now) {
        return priceVersionMapper.selectNewestVersionByFidAndDate(projectFid, versionTypes, versionStates, isDel, now);
    }

    /**
     * 查询指定归属月和分期的货值最新版本
     * @param projectFid 分期id
     * @param versionType 货值版本
     * @param ascriptionDate 归属月份
     * @param isDel 是否删除
     * @return PriceVersion
     */
    @Override
    public PriceVersion selectNewestDynamicToMonthByPrice(String projectFid, String versionType, LocalDate ascriptionDate, int isDel) {
        return priceVersionMapper.selectNewestDynamicToMonthByPrice(projectFid, versionType, ascriptionDate, isDel);
    }

    /**
     *  货值指定定稿
     * @param stageId 分期id
     * @param finalizationTime 定稿时间
     */
    @Override
    public synchronized void priceFinalizationToProjectAndTime(String stageId, String finalizationTime) {
    	//TODO 明源签约数据改成ESB下发，上线需修改
        try{
            dmOdsMyVsMarsSContractServiceImpl.syncIncrement();
        }catch (Exception e){
            logger.error("#########  增量拉取明源签约数据接口  错误信息："+e.getMessage(), e);
        }

        //增量拉取NOS数据接口
        try {
            dmOdsNosTradedataviewformarsService.syncNosContact();
        }catch (Exception e){
            logger.error("#########  NOS 全量拉取签约数据接口 错误信息："+e.getMessage(), e);
        }

        LocalDateTime now = LocalDateTime.now();
        LocalDate finalizationtime = LocalDate.parse(finalizationTime, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        supplyPlanTasks.finalizeTaskInfo(now, finalizationtime, new ArrayList<String>(), stageId);
    }

    /**
     *  货值导出
     * @param versionId 货值id
     */
    @Override
    public void priceExcelExport(String versionId, HttpServletRequest request, HttpServletResponse response) {

        List<PriceExcelExportVO> result = new ArrayList<PriceExcelExportVO>();
        String versionType = "";
        String projectName = "";
        String stageName = "";
        String versionName = "";
        String assessmentName = "";
        LocalDateTime updateTime = null;

        PriceVersion priceVersion = priceVersionMapper.selectByPrimaryKey(versionId);
        if(priceVersion != null){
            String projectId = priceVersion.getProjectId();
            String projectfId = priceVersion.getProjectfId();
            Integer isAssessmentVersion = priceVersion.getIsAssessmentVersion();
            if(isAssessmentVersion != null && isAssessmentVersion.equals(IsDeleteEnum.YES.getKey())){
                assessmentName = "(考核版)";
            }

            versionType = priceVersion.getVersionType();
            MdmProject mdmProject = projectService.selectByProjectId(projectId, IsDeleteEnum.NO.getKey());
            StagePartNers partner = stagePartNersService.getStagePartnersByProjectFid(projectfId);
            if(null == partner){
                partner = new StagePartNers();
            }

            QueryWrapper<PriceValueOrg> stageWrapper = new QueryWrapper<PriceValueOrg>();
            stageWrapper.eq("version_id", versionId)
                    .eq("type", OrgTypeEunm.ORG_STAGE.getKey())
                    .eq("is_delete", IsDeleteEnum.NO.getKey());
            PriceValueOrg stageOrg = priceValueOrgMapper.selectOne(stageWrapper);
            PriceExcelExportVO stageVo = new PriceExcelExportVO();

            projectName = mdmProject.getProjectName();
            projectName = projectName.replaceAll("/", "_");
            stageName = stageOrg.getOrgName();
            versionName = priceVersion.getVersionName();
            updateTime = priceVersion.getUpdateTime();

            stageVo.setProjectName(mdmProject.getProjectName());
            stageVo.setProjectCode(mdmProject.getProjectCode());
            stageVo.setType(stageOrg.getType());

            stageVo.setStageName(stageOrg.getOrgName());
            stageVo.setStageCode(priceVersion.getStageCode());
            stageVo.setStageEquityRatio(partner.getEquityRatio()+"%");
            stageVo.setIsMarket(priceVersion.getIsMarket().equals(MarketingEunm.IS_MARKET.getKey())?MarketingEunm.IS_MARKET.getValue():MarketingEunm.IS_NOT_MARKET.getValue());
            stageVo.setPartTable(partner.getPartNerIsAndTable().equals("1")?"是":"否");

            if (stageOrg.getAveragePriceHouse() != null || stageOrg.getAveragePriceParking() != null){
                stageVo.setAveragePrice((stageOrg.getAveragePriceHouse()==null?new BigDecimal(0):stageOrg.getAveragePriceHouse()).setScale(0,BigDecimal.ROUND_UP)
                        +"/"+(stageOrg.getAveragePriceParking()==null?new BigDecimal(0):stageOrg.getAveragePriceParking()).setScale(0,BigDecimal.ROUND_UP));
            }

            if (stageOrg.getRoomNum() != null || stageOrg.getParkingNum() != null){
                stageVo.setNum((stageOrg.getRoomNum()==null?"":stageOrg.getRoomNum())
                        +"/"+(stageOrg.getParkingNum()==null?"":stageOrg.getParkingNum()));
            }

            if (stageOrg.getSaleArea() != null){
                stageVo.setArea((stageOrg.getSaleArea()==null?"":stageOrg.getSaleArea())+"");
            }

            if (stageOrg.getHouseCommodityValue() != null || stageOrg.getNotCommodityValue() != null){
                stageVo.setPrice(NumberUtils.fmtToWanUnit(BigDecimalADD(stageOrg.getHouseCommodityValue(), stageOrg.getNotCommodityValue()).toString()) +"/"+
                        NumberUtils.fmtToWanUnit((stageOrg.getHouseCommodityValue()==null?"":stageOrg.getHouseCommodityValue()).toString())
                        +"/"+NumberUtils.fmtToWanUnit((stageOrg.getNotCommodityValue()==null?"":stageOrg.getNotCommodityValue()).toString()));
            }

            if (stageOrg.getForsaleParkingNum() != null){
                stageVo.setNotNum((stageOrg.getForsaleParkingNum()==null?"":stageOrg.getForsaleParkingNum())+"");
            }

            if (stageOrg.getCommodityValue() != null){
                stageVo.setNotPrice(NumberUtils.fmtToWanUnit((stageOrg.getCommodityValue()==null?"":stageOrg.getCommodityValue()).toString()));
            }
            result.add(stageVo);

            QueryWrapper<PriceValueOrg> groupWrapper = new QueryWrapper<PriceValueOrg>();
            groupWrapper.eq("version_id", versionId)
                    .eq("type", OrgTypeEunm.ORG_GROUP.getKey())
                    .eq("is_delete", IsDeleteEnum.NO.getKey());
            List<PriceValueOrg> groupOrgs = priceValueOrgMapper.selectList(groupWrapper);
            groupOrgs.sort((a, b) -> {
                return groupExportSortInfo(a.getOrgName(), b.getOrgName(), "车位");
            });

            //导出投资版
            if (versionType.equals(VersionTypeEunm.INVESTMENT.getKey())){

                QueryWrapper<PriceValueOrg> batchWrapper = new QueryWrapper<PriceValueOrg>();
                batchWrapper.eq("version_id", versionId)
                        .eq("type", OrgTypeEunm.ORG_BATCH.getKey())
                        .eq("is_delete", IsDeleteEnum.NO.getKey());
                List<PriceValueOrg> batchOrgs = priceValueOrgMapper.selectList(batchWrapper);
                if (CollectionUtils.isNotEmpty(batchOrgs)) {
                    InvestmentExportSortInfo(batchOrgs);
                }

                QueryWrapper<PriceValueOrg> productWrapper = new QueryWrapper<PriceValueOrg>();
                productWrapper.eq("version_id", versionId)
                        .eq("type", OrgTypeEunm.ORG_PRODUCT.getKey())
                        .eq("is_delete", IsDeleteEnum.NO.getKey());
                List<PriceValueOrg> productOrgs = priceValueOrgMapper.selectList(productWrapper);

                QueryWrapper<PriceValueOrg> ortherWrapper = new QueryWrapper<PriceValueOrg>();
                ortherWrapper.eq("version_id", versionId)
                        .in("type", OrgTypeEunm.ORG_SALE_PACKAGE.getKey(), OrgTypeEunm.ORG_NOT_SALE_PACKAGE.getKey(),
                                OrgTypeEunm.ORG_SALING_PARKING.getKey(), OrgTypeEunm.ORG_NOT_SALING_PARKING.getKey())
                        .eq("is_delete", IsDeleteEnum.NO.getKey());
                List<PriceValueOrg> ortherOrgs = priceValueOrgMapper.selectList(ortherWrapper);

                List<PriceValueCastDecisionEXTBO> productGroupOrgs = priceValueOrgMapper.selectProductByVersionIdGroup(priceVersion.getId(), OrgTypeEunm.ORG_PRODUCT.getKey(), IsDeleteEnum.NO.getKey());

                //投资版数据循环
                investmentExportItemInfo(result, priceVersion, mdmProject, partner, stageOrg, groupOrgs, batchOrgs, productOrgs, ortherOrgs, productGroupOrgs);
            }else{ //导出战规后版本
                QueryWrapper<PriceValueOrg> productWrapper = new QueryWrapper<PriceValueOrg>();
                productWrapper.eq("version_id", versionId)
                        .eq("type", OrgTypeEunm.ORG_PRODUCT.getKey())
                        .eq("is_delete", IsDeleteEnum.NO.getKey());
                List<PriceValueOrg> productOrgs = priceValueOrgMapper.selectList(productWrapper);

                QueryWrapper<PriceValueOrg> buildWrapper = new QueryWrapper<PriceValueOrg>();
                buildWrapper.eq("version_id", versionId)
                        .eq("type", OrgTypeEunm.ORG_BUILD.getKey())
                        .eq("is_delete", IsDeleteEnum.NO.getKey());
                List<PriceValueOrg> buildOrgs = priceValueOrgMapper.selectList(buildWrapper);

                QueryWrapper<PriceValueOrg> houseWrapper = new QueryWrapper<PriceValueOrg>();
                houseWrapper.eq("version_id", versionId)
                        .eq("type", OrgTypeEunm.ORG_HOUSE_PACKAGE.getKey())
                        .eq("is_delete", IsDeleteEnum.NO.getKey());
                List<PriceValueOrg> houseOrgs = priceValueOrgMapper.selectList(houseWrapper);
                if (CollectionUtils.isNotEmpty(houseOrgs)) {
                    warPlanExportSortInfo(houseOrgs);
                }

                QueryWrapper<PriceValueOrg> parkingWrapper = new QueryWrapper<PriceValueOrg>();
                parkingWrapper.eq("version_id", versionId)
                        .in("type", OrgTypeEunm.ORG_HOUSE_PACKAGE.getKey(), OrgTypeEunm.ORG_SALE_PACKAGE.getKey(), OrgTypeEunm.ORG_NOT_SALE_PACKAGE.getKey(),
                                OrgTypeEunm.ORG_SALING_PARKING.getKey(), OrgTypeEunm.ORG_NOT_SALING_PARKING.getKey())
                        .eq("is_delete", IsDeleteEnum.NO.getKey());
                List<PriceValueOrg> parkingOrgs = priceValueOrgMapper.selectList(parkingWrapper);

                //战规后数据循环
                warPlanExportItemInfo(result, priceVersion, mdmProject, partner, stageOrg, groupOrgs, productOrgs, buildOrgs, houseOrgs, parkingOrgs);
            }
        }else{
            throw new MsgException(CodeEnum.NON_EXISTENT_VERSIONS);
        }

        try{
            String reportName = String.format(projectName+stageName+"货值-"+versionName+"-"+updateTime.format(DateTimeFormatter.ofPattern("yyyyMMdd")));
            if(versionType.equals(VersionTypeEunm.INVESTMENT.getKey())){
                reportName = reportName + assessmentName;
            }
            reportName = reportName +"-"+LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHH"));
            String sheetName = String.format(projectName+stageName+"货值-"+versionName);
            PriceValueReportTemplate priceValueReportTemplate = new PriceValueReportTemplate();
            priceValueReportTemplate.appendRows(result);
            priceValueReportTemplate.setSheetName(sheetName);
            try (OutputStream outputStream = response.getOutputStream()) {
                response.setContentType("application/vnd.ms-excel");
                response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(reportName + ".xls", "utf-8"));
                priceValueReportTemplate.write(outputStream);
                outputStream.flush();
            } catch (IOException e) {
                logger.error(e.getMessage(), e);
            }
        }catch (Exception e){
            logger.error(e.getMessage(), e);
        }
    }

    private int groupExportSortInfo(String orgName, String orgName2, String 车位) {
        String aName = orgName;
        String bName = orgName2;

        String[] aStr = aName.split("组团");
        String[] bStr = bName.split("组团");

        if (aStr[0].equals(车位)) {
            aStr[0] = "10000000";
        }
        if (bStr[0].equals(车位)) {
            bStr[0] = "10000000";
        }

        String aValue = NumberEnum.getKeyByValue(aStr[0]);
        String bValue = NumberEnum.getKeyByValue(bStr[0]);

        return aValue == null ? 1 : bValue == null ? -1 : Integer.valueOf(aValue) - Integer.valueOf(bValue);
    }

    private void InvestmentExportSortInfo(List<PriceValueOrg> batchOrgs) {
        batchOrgs.sort((a, b) -> {
            String aName = a.getOrgName();
            String bName = b.getOrgName();

            String[] aStr = aName.split("批次");
            String[] bStr = bName.split("批次");

            String aValue = NumberEnum.getKeyByValue(aStr[0]);
            String bValue = NumberEnum.getKeyByValue(bStr[0]);

            return aValue == null ? 1 : bValue == null ? -1 : Integer.valueOf(aValue) - Integer.valueOf(bValue);
        });
    }

    private void warPlanExportSortInfo(List<PriceValueOrg> houseOrgs) {
        houseOrgs.sort((a,b)->{
            String aAreaPart = a.getAreaPart();
            String bAreaPart = b.getAreaPart();

            Integer aComStr = 0;
            Integer bComStr = 0;

            if(aAreaPart.equals(Constants.ORTHER_HOUSE_NAME)){
                aComStr = 10000000;
            }else{
                String[] aAplitStr = aAreaPart.split("-");
                aComStr = Integer.valueOf(aAplitStr[0]);
            }

            if (bAreaPart.equals(Constants.ORTHER_HOUSE_NAME)){
                bComStr = 10000000;
            }else{
                String[] bSplitStr = bAreaPart.split("-");
                bComStr = Integer.valueOf(bSplitStr[0]);
            }

            return aComStr.compareTo(bComStr);
        });
    }

    /**
     * 货值投资版导出
     */
    private void investmentExportItemInfo(List<PriceExcelExportVO> result, PriceVersion priceVersion, MdmProject mdmProject, StagePartNers partner, PriceValueOrg stageOrg, List<PriceValueOrg> groupOrgs, List<PriceValueOrg> batchOrgs, List<PriceValueOrg> productOrgs, List<PriceValueOrg> ortherOrgs, List<PriceValueCastDecisionEXTBO> productGroupOrgs) {
        for (PriceValueOrg groupOrg : groupOrgs) {
            investmentExportGroupItemInfo(result, priceVersion, mdmProject, partner, stageOrg, batchOrgs, productOrgs, ortherOrgs, productGroupOrgs, groupOrg);
        }
    }

    private void investmentExportGroupItemInfo(List<PriceExcelExportVO> result, PriceVersion priceVersion, MdmProject mdmProject, StagePartNers partner, PriceValueOrg stageOrg, List<PriceValueOrg> batchOrgs, List<PriceValueOrg> productOrgs, List<PriceValueOrg> ortherOrgs, List<PriceValueCastDecisionEXTBO> productGroupOrgs, PriceValueOrg groupOrg) {
        String groupId = groupOrg.getId();

        PriceExcelExportVO groupVo = new PriceExcelExportVO();
        groupVo.setType(groupOrg.getType());
        groupVo.setProjectName(mdmProject.getProjectName());
        groupVo.setProjectCode(mdmProject.getProjectCode());

        groupVo.setStageName(stageOrg.getOrgName());
        groupVo.setStageCode(priceVersion.getStageCode());
        groupVo.setStageEquityRatio(partner.getEquityRatio()+"%");
        groupVo.setIsMarket(priceVersion.getIsMarket().equals(MarketingEunm.IS_MARKET.getKey())?MarketingEunm.IS_MARKET.getValue():MarketingEunm.IS_NOT_MARKET.getValue());
        groupVo.setPartTable(partner.getPartNerIsAndTable().equals("1")?"是":"否");

        groupVo.setGroupName(groupOrg.getOrgName());

        if (groupOrg.getAveragePriceHouse() != null || groupOrg.getAveragePriceParking() != null){
            groupVo.setAveragePrice((groupOrg.getAveragePriceHouse()==null?new BigDecimal(0):groupOrg.getAveragePriceHouse()).setScale(0,BigDecimal.ROUND_UP)
                    +"/"+(groupOrg.getAveragePriceParking()==null?new BigDecimal(0):groupOrg.getAveragePriceParking()).setScale(0,BigDecimal.ROUND_UP));
        }

        if (groupOrg.getRoomNum() != null || groupOrg.getParkingNum() != null){
            groupVo.setNum((groupOrg.getRoomNum()==null?"":groupOrg.getRoomNum())
                    +"/"+(groupOrg.getParkingNum()==null?"":groupOrg.getParkingNum()));
        }

        if (groupOrg.getSaleArea() != null){
            groupVo.setArea((groupOrg.getSaleArea()==null?"":groupOrg.getSaleArea())+"");
        }

        if (groupOrg.getHouseCommodityValue() != null || groupOrg.getNotCommodityValue() != null){
            groupVo.setPrice(NumberUtils.fmtToWanUnit(BigDecimalADD(groupOrg.getHouseCommodityValue(), groupOrg.getNotCommodityValue()).toString())
                    +"/"+NumberUtils.fmtToWanUnit((groupOrg.getHouseCommodityValue()==null?"":groupOrg.getHouseCommodityValue().toString()))
                    +"/"+NumberUtils.fmtToWanUnit((groupOrg.getNotCommodityValue()==null?"":groupOrg.getNotCommodityValue()).toString()));
        }

        if (groupOrg.getForsaleParkingNum() != null && !groupOrg.getForsaleParkingNum().equals(0)){
            groupVo.setNotNum((groupOrg.getForsaleParkingNum()==null?"":groupOrg.getForsaleParkingNum())+"");
        }

        if (groupOrg.getCommodityValue() != null && groupOrg.getCommodityValue().compareTo(new BigDecimal(0)) != 0){
            groupVo.setNotPrice(NumberUtils.fmtToWanUnit((groupOrg.getCommodityValue()==null?"":groupOrg.getCommodityValue()).toString()));
        }
        result.add(groupVo);

        for (PriceValueCastDecisionEXTBO productGroupOrg : productGroupOrgs) {
            investmentExportProductItemInfo(result, priceVersion, mdmProject, partner, stageOrg, batchOrgs, productOrgs, ortherOrgs, groupOrg, groupId, productGroupOrg);
        }
    }

    private void investmentExportProductItemInfo(List<PriceExcelExportVO> result, PriceVersion priceVersion, MdmProject mdmProject, StagePartNers partner, PriceValueOrg stageOrg, List<PriceValueOrg> batchOrgs, List<PriceValueOrg> productOrgs, List<PriceValueOrg> ortherOrgs, PriceValueOrg groupOrg, String groupId, PriceValueCastDecisionEXTBO productGroupOrg) {
        if(productGroupOrg.getGroupId().equals(groupOrg.getId())){
            PriceExcelExportVO productGroupVo = new PriceExcelExportVO();

            productGroupVo.setType(productGroupOrg.getType());
            productGroupVo.setProjectName(mdmProject.getProjectName());
            productGroupVo.setProjectCode(mdmProject.getProjectCode());

            productGroupVo.setStageName(stageOrg.getOrgName());
            productGroupVo.setStageCode(priceVersion.getStageCode());

            productGroupVo.setStageEquityRatio(partner.getEquityRatio()+"%");
            productGroupVo.setIsMarket(priceVersion.getIsMarket().equals(MarketingEunm.IS_MARKET.getKey())?MarketingEunm.IS_MARKET.getValue():MarketingEunm.IS_NOT_MARKET.getValue());
            productGroupVo.setPartTable(partner.getPartNerIsAndTable().equals("1")?"是":"否");

            productGroupVo.setGroupName(groupOrg.getOrgName());
            productGroupVo.setProductName(productGroupOrg.getOrgName());

            productGroupVo.setProProductName(productGroupOrg.getProProductType());
            productGroupVo.setProProductCode(productGroupOrg.getProProductCode());
            productGroupVo.setProductName(productGroupOrg.getOrgName());
            productGroupVo.setProductCode(productGroupOrg.getOrgCode());

            Integer collectNum = 0;
            BigDecimal collectArea = new BigDecimal(0);

            Integer collectNotNum = 0;

            BigDecimal collectPrice = new BigDecimal(0);
            BigDecimal collectNotPrice = new BigDecimal(0);

            List<PriceExcelExportVO> productList = new ArrayList<PriceExcelExportVO>();
            for (PriceValueOrg batchOrg : batchOrgs){
                String batchId = batchOrg.getId();

                if (batchOrg.getPid().equals(groupId)){

                    wc:for (PriceValueOrg productOrg : productOrgs){
                        if(!productOrg.getProductCode().equals(productGroupOrg.getProductCode())){
                            continue wc;
                        }
                        String productId = productOrg.getId();

                        if (productOrg.getBusinessType().equals(SalyTypeEnum.SALABLE.getKey())
                                || productOrg.getBusinessType().equals(SalyTypeEnum.STAGE_SELF_SUSTAINMENT.getKey())){
                            if (productOrg.getPid().equals(batchId)){
                                PriceExcelExportVO productVo = new PriceExcelExportVO();
                                productVo.setType(batchOrg.getType());
                                productVo.setProjectName(mdmProject.getProjectName());
                                productVo.setProjectCode(mdmProject.getProjectCode());

                                productVo.setStageName(stageOrg.getOrgName());
                                productVo.setStageCode(priceVersion.getStageCode());
                                productVo.setStageEquityRatio(partner.getEquityRatio()+"%");
                                productVo.setIsMarket(priceVersion.getIsMarket().equals(MarketingEunm.IS_MARKET.getKey())?MarketingEunm.IS_MARKET.getValue():MarketingEunm.IS_NOT_MARKET.getValue());
                                productVo.setPartTable(partner.getPartNerIsAndTable().equals("1")?"是":"否");

                                productVo.setGroupName(groupOrg.getOrgName());

                                productVo.setProProductName(productOrg.getProProductType());
                                productVo.setProProductCode(productOrg.getProProductCode());
                                productVo.setProductName(productOrg.getOrgName());
                                productVo.setProductCode(productOrg.getOrgCode());

                                productVo.setBuildName(batchOrg.getOrgName());
                                productVo.setBusinessType(productOrg.getBusinessTypeName());
                                productVo.setFreeType(productOrg.getFreeTypeName());
                                productVo.setProType(productOrg.getProTypeName());

                                if(productOrg.getSupplyTime() != null){
                                    productVo.setSupplyTime(productOrg.getSupplyTime().toLocalDate());
                                }
                                if(productOrg.getSupplyTimeActual() != null){
                                    productVo.setSupplyTimeActual(productOrg.getSupplyTimeActual().toLocalDate());
                                }
                                if(productOrg.getSupplyTimeVirtual() != null){
                                    productVo.setSupplyTimeVirtual(productOrg.getSupplyTimeVirtual().toLocalDate());
                                }

                                if(productOrg.getIsParking().equals(IsDeleteEnum.NO.getKey())){
                                    productVo.setAveragePrice(NumberUtils.fmtTo(productOrg.getAveragePriceHouse()==null?new BigDecimal(0):productOrg.getAveragePriceHouse()));
                                    productVo.setNum((productOrg.getRoomNum()==null?"0":productOrg.getRoomNum())+"");
                                    productVo.setArea((productOrg.getSaleArea()==null?"0":productOrg.getSaleArea())+"");
                                    productVo.setPrice(NumberUtils.fmtToWanUnit((productOrg.getHouseCommodityValue()==null?"0":productOrg.getHouseCommodityValue()).toString()));

                                    collectNum = collectNum + (productOrg.getRoomNum()==null?0:productOrg.getRoomNum());
                                    collectArea = BigDecimalADD(collectArea, productOrg.getSaleArea());
                                    collectPrice = BigDecimalADD(collectPrice, productOrg.getHouseCommodityValue());
                                }else{
                                    productVo.setAveragePrice(NumberUtils.fmtTo((productOrg.getAveragePriceParking()==null?new BigDecimal(0):productOrg.getAveragePriceParking())));
                                    productVo.setNum((productOrg.getParkingNum()==null?"0":productOrg.getParkingNum())+"");
                                    productVo.setPrice(NumberUtils.fmtToWanUnit((productOrg.getNotCommodityValue()==null?"0":productOrg.getNotCommodityValue()).toString()));

                                    productVo.setNotNum((productOrg.getForsaleParkingNum()==null?"0":productOrg.getForsaleParkingNum())+"");
                                    productVo.setNotPrice(NumberUtils.fmtToWanUnit((productOrg.getCommodityValue()==null?"0":productOrg.getCommodityValue()).toString()));

                                    collectNum = collectNum + (productOrg.getParkingNum()==null?0:productOrg.getParkingNum());
                                    collectPrice = BigDecimalADD(collectPrice, productOrg.getNotCommodityValue());

                                    collectNotNum = collectNotNum + (productOrg.getForsaleParkingNum()==null?0:productOrg.getForsaleParkingNum());
                                    collectNotPrice = BigDecimalADD(collectNotPrice, productOrg.getCommodityValue());
                                }

                                productList.add(productVo);

                                if (CollectionUtils.isNotEmpty(ortherOrgs)){
                                    for (PriceValueOrg ortherOrg : ortherOrgs) {
                                        investmentExportParkingItemInfo(priceVersion, mdmProject, partner, stageOrg, groupOrg, productList, batchOrg, productOrg, productId, ortherOrg);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if(productGroupOrg.getIsParking().equals(IsDeleteEnum.NO.getKey())){
                productGroupVo.setNum((collectNum==null?"0":collectNum)+"");
                productGroupVo.setArea((collectArea==null?"0":collectArea)+"");
                productGroupVo.setPrice(NumberUtils.fmtToWanUnit((collectPrice==null?"":collectPrice).toString()));
                productGroupVo.setAveragePrice(StrUtils.bigDecimalDIV(collectPrice, collectArea).setScale(0,BigDecimal.ROUND_UP)+"");
            }else{
                productGroupVo.setNum((collectNum==null?"0":collectNum)+"");
                productGroupVo.setPrice(NumberUtils.fmtToWanUnit((collectPrice==null?"0":collectPrice).toString()));
                productGroupVo.setAveragePrice(StrUtils.bigDecimalDIV(collectPrice, new BigDecimal(collectNum)).setScale(0,BigDecimal.ROUND_UP)+"");

                productGroupVo.setNotNum((collectNotNum==null?"0":collectNotNum)+"");
                productGroupVo.setNotPrice(NumberUtils.fmtToWanUnit((collectNotPrice==null?"":collectNotPrice).toString()));
            }

            result.add(productGroupVo);
            result.addAll(productList);
        }
    }

    private void investmentExportParkingItemInfo(PriceVersion priceVersion, MdmProject mdmProject, StagePartNers partner, PriceValueOrg stageOrg, PriceValueOrg groupOrg, List<PriceExcelExportVO> productList, PriceValueOrg batchOrg, PriceValueOrg productOrg, String productId, PriceValueOrg ortherOrg) {
        if (ortherOrg.getPid().equals(productId)){
            PriceExcelExportVO ortherVo = new PriceExcelExportVO();
            ortherVo.setType(ortherOrg.getType());
            ortherVo.setProjectName(mdmProject.getProjectName());
            ortherVo.setProjectCode(mdmProject.getProjectCode());

            ortherVo.setStageName(stageOrg.getOrgName());
            ortherVo.setStageCode(priceVersion.getStageCode());
            ortherVo.setStageEquityRatio(partner.getEquityRatio()+"%");
            ortherVo.setIsMarket(priceVersion.getIsMarket().equals(MarketingEunm.IS_MARKET.getKey())?MarketingEunm.IS_MARKET.getValue():MarketingEunm.IS_NOT_MARKET.getValue());
            ortherVo.setPartTable(partner.getPartNerIsAndTable().equals("1")?"是":"否");

            ortherVo.setGroupName(groupOrg.getOrgName());

            ortherVo.setProProductName(productOrg.getProProductType());
            ortherVo.setProProductCode(productOrg.getProProductCode());
            ortherVo.setProductName(productOrg.getOrgName());
            ortherVo.setProductCode(productOrg.getOrgCode());

            ortherVo.setBuildName(batchOrg.getOrgName());

            ortherVo.setBusinessType(productOrg.getBusinessTypeName());
            ortherVo.setFreeType(productOrg.getFreeTypeName());
            ortherVo.setProType(productOrg.getProTypeName());

            ortherVo.setAreaPart(ortherOrg.getOrgName());

            if (ortherOrg.getType().equals(OrgTypeEunm.ORG_SALING_PARKING.getKey())){
                ortherVo.setAveragePrice(NumberUtils.fmtTo((ortherOrg.getAveragePriceParking()==null?new BigDecimal(0):ortherOrg.getAveragePriceParking())));
                ortherVo.setNum((ortherOrg.getParkingNum()==null?"0":ortherOrg.getParkingNum())+"");
                ortherVo.setPrice(NumberUtils.fmtToWanUnit((ortherOrg.getNotCommodityValue()==null?"0":ortherOrg.getNotCommodityValue()).toString()));
            }else{
                ortherVo.setAveragePrice(NumberUtils.fmtTo(StrUtils.bigDecimalDIV(ortherOrg.getCommodityValue(), new BigDecimal(ortherOrg.getForsaleParkingNum()))));
                ortherVo.setNotNum((ortherOrg.getForsaleParkingNum()==null?"0":ortherOrg.getForsaleParkingNum())+"");
                ortherVo.setNotPrice(NumberUtils.fmtToWanUnit((ortherOrg.getCommodityValue()==null?"0":ortherOrg.getCommodityValue()).toString()));
            }
            productList.add(ortherVo);
        }
    }

    /**
     * 货值战规后导出
     */
    private void warPlanExportItemInfo(List<PriceExcelExportVO> result, PriceVersion priceVersion, MdmProject mdmProject, StagePartNers partner, PriceValueOrg stageOrg, List<PriceValueOrg> groupOrgs, List<PriceValueOrg> productOrgs, List<PriceValueOrg> buildOrgs, List<PriceValueOrg> houseOrgs, List<PriceValueOrg> parkingOrgs) {
        for (PriceValueOrg groupOrg : groupOrgs) {
            warPlanExportIGroupItemInfo(result, priceVersion, mdmProject, partner, stageOrg, productOrgs, buildOrgs, houseOrgs, parkingOrgs, groupOrg);
        }
    }

    private void warPlanExportIGroupItemInfo(List<PriceExcelExportVO> result, PriceVersion priceVersion, MdmProject mdmProject, StagePartNers partner, PriceValueOrg stageOrg, List<PriceValueOrg> productOrgs, List<PriceValueOrg> buildOrgs, List<PriceValueOrg> houseOrgs, List<PriceValueOrg> parkingOrgs, PriceValueOrg groupOrg) {
        String groupId = groupOrg.getId();

        PriceExcelExportVO groupVo = new PriceExcelExportVO();
        groupVo.setType(groupOrg.getType());
        groupVo.setProjectName(mdmProject.getProjectName());
        groupVo.setProjectCode(mdmProject.getProjectCode());

        groupVo.setStageName(stageOrg.getOrgName());
        groupVo.setStageCode(priceVersion.getStageCode());
        groupVo.setStageEquityRatio(partner.getEquityRatio()+"%");
        groupVo.setIsMarket(priceVersion.getIsMarket().equals(MarketingEunm.IS_MARKET.getKey())?MarketingEunm.IS_MARKET.getValue():MarketingEunm.IS_NOT_MARKET.getValue());
        groupVo.setPartTable(partner.getPartNerIsAndTable().equals("1")?"是":"否");

        groupVo.setGroupName(groupOrg.getOrgName());

        if (groupOrg.getAveragePriceHouse() != null || groupOrg.getAveragePriceParking() != null){
            groupVo.setAveragePrice((groupOrg.getAveragePriceHouse()==null?new BigDecimal(0):groupOrg.getAveragePriceHouse()).setScale(0,BigDecimal.ROUND_UP)
                    +"/"+(groupOrg.getAveragePriceParking()==null?new BigDecimal(0):groupOrg.getAveragePriceParking()).setScale(0,BigDecimal.ROUND_UP));
        }

        if (groupOrg.getRoomNum() != null || groupOrg.getParkingNum() != null){
            groupVo.setNum((groupOrg.getRoomNum()==null?"0":groupOrg.getRoomNum())
                    +"/"+(groupOrg.getParkingNum()==null?"0":groupOrg.getParkingNum()));
        }

        if (groupOrg.getSaleArea() != null){
            groupVo.setArea((groupOrg.getSaleArea()==null?"0":groupOrg.getSaleArea())+"");
        }

        if (groupOrg.getHouseCommodityValue() != null || groupOrg.getNotCommodityValue() != null){
            groupVo.setPrice(NumberUtils.fmtToWanUnit(BigDecimalADD(groupOrg.getHouseCommodityValue(), groupOrg.getNotCommodityValue()).toString())
                    +"/"+NumberUtils.fmtToWanUnit((groupOrg.getHouseCommodityValue()==null?"":groupOrg.getHouseCommodityValue()).toString())
                    +"/"+NumberUtils.fmtToWanUnit((groupOrg.getNotCommodityValue()==null?"":groupOrg.getNotCommodityValue()).toString()));
        }

        if (groupOrg.getForsaleParkingNum() != null && !groupOrg.getForsaleParkingNum().equals(0)){
            groupVo.setNotNum((groupOrg.getForsaleParkingNum()==null?"":groupOrg.getForsaleParkingNum())+"");
        }

        if (groupOrg.getCommodityValue() != null && groupOrg.getCommodityValue().compareTo(new BigDecimal(0)) != 0){
            groupVo.setNotPrice(NumberUtils.fmtToWanUnit((groupOrg.getCommodityValue()==null?"":groupOrg.getCommodityValue()).toString()));
        }

        result.add(groupVo);

        for (PriceValueOrg productOrg : productOrgs) {
            warPlanExportIProductItemInfo(result, priceVersion, mdmProject, partner, stageOrg, buildOrgs, houseOrgs, parkingOrgs, groupOrg, groupId, productOrg);
        }
    }

    private void warPlanExportIProductItemInfo(List<PriceExcelExportVO> result, PriceVersion priceVersion, MdmProject mdmProject, StagePartNers partner, PriceValueOrg stageOrg, List<PriceValueOrg> buildOrgs, List<PriceValueOrg> houseOrgs, List<PriceValueOrg> parkingOrgs, PriceValueOrg groupOrg, String groupId, PriceValueOrg productOrg) {
        String productId = productOrg.getId();

        if (productOrg.getPid().equals(groupId)){
            PriceExcelExportVO productVo = new PriceExcelExportVO();
            productVo.setType(productOrg.getType());
            productVo.setProjectName(mdmProject.getProjectName());
            productVo.setProjectCode(mdmProject.getProjectCode());

            productVo.setStageName(stageOrg.getOrgName());
            productVo.setStageCode(priceVersion.getStageCode());
            productVo.setStageEquityRatio(partner.getEquityRatio()+"%");
            productVo.setIsMarket(priceVersion.getIsMarket().equals(MarketingEunm.IS_MARKET.getKey())?MarketingEunm.IS_MARKET.getValue():MarketingEunm.IS_NOT_MARKET.getValue());
            productVo.setPartTable(partner.getPartNerIsAndTable().equals("1")?"是":"否");

            productVo.setGroupName(groupOrg.getOrgName());

            productVo.setProProductName(productOrg.getProProductType());
            productVo.setProProductCode(productOrg.getProProductCode());
            productVo.setProductName(productOrg.getOrgName());
            productVo.setProductCode(productOrg.getOrgCode());

            if(productOrg.getIsParking().equals(IsDeleteEnum.NO.getKey())){
                productVo.setAveragePrice(NumberUtils.fmtTo((productOrg.getAveragePriceHouse()==null?new BigDecimal(0):productOrg.getAveragePriceHouse())));
                productVo.setNum((productOrg.getRoomNum()==null?"0":productOrg.getRoomNum())+"");
                productVo.setArea((productOrg.getSaleArea()==null?"0":productOrg.getSaleArea())+"");
                productVo.setPrice(NumberUtils.fmtToWanUnit((productOrg.getHouseCommodityValue()==null?"0":productOrg.getHouseCommodityValue()).toString()));
            }else{
                productVo.setAveragePrice(NumberUtils.fmtTo((productOrg.getAveragePriceParking()==null?new BigDecimal(0):productOrg.getAveragePriceParking())));
                productVo.setNum((productOrg.getParkingNum()==null?"0":productOrg.getParkingNum())+"");
                productVo.setPrice(NumberUtils.fmtToWanUnit((productOrg.getNotCommodityValue()==null?"0":productOrg.getNotCommodityValue()).toString()));

                productVo.setNotNum((productOrg.getForsaleParkingNum()==null?"0":productOrg.getForsaleParkingNum())+"");
                productVo.setNotPrice(NumberUtils.fmtToWanUnit((productOrg.getCommodityValue()==null?"0":productOrg.getCommodityValue()).toString()));
            }

            result.add(productVo);

            for (PriceValueOrg buildOrg : buildOrgs) {
                warPlanExportIBuildItemInfo(result, priceVersion, mdmProject, partner, stageOrg, houseOrgs, parkingOrgs, groupOrg, productOrg, productId, buildOrg);
            }
        }
    }

    private void warPlanExportIBuildItemInfo(List<PriceExcelExportVO> result, PriceVersion priceVersion, MdmProject mdmProject, StagePartNers partner, PriceValueOrg stageOrg, List<PriceValueOrg> houseOrgs, List<PriceValueOrg> parkingOrgs, PriceValueOrg groupOrg, PriceValueOrg productOrg, String productId, PriceValueOrg buildOrg) {
        String buildId = buildOrg.getId();

        if (buildOrg.getBusinessType().equals(SalyTypeEnum.SALABLE.getKey())
                || buildOrg.getBusinessType().equals(SalyTypeEnum.STAGE_SELF_SUSTAINMENT.getKey())){
            if (buildOrg.getPid().equals(productId)) {
                PriceExcelExportVO buildVo = new PriceExcelExportVO();
                buildVo.setType(buildOrg.getType());
                buildVo.setProjectName(mdmProject.getProjectName());
                buildVo.setProjectCode(mdmProject.getProjectCode());

                buildVo.setStageName(stageOrg.getOrgName());
                buildVo.setStageCode(priceVersion.getStageCode());
                buildVo.setStageEquityRatio(partner.getEquityRatio()+"%");
                buildVo.setIsMarket(priceVersion.getIsMarket().equals(MarketingEunm.IS_MARKET.getKey())?MarketingEunm.IS_MARKET.getValue():MarketingEunm.IS_NOT_MARKET.getValue());
                buildVo.setPartTable(partner.getPartNerIsAndTable().equals("1")?"是":"否");

                buildVo.setGroupName(groupOrg.getOrgName());

                buildVo.setProProductName(productOrg.getProProductType());
                buildVo.setProProductCode(productOrg.getProProductCode());
                buildVo.setProductName(productOrg.getOrgName());
                buildVo.setProductCode(productOrg.getOrgCode());

                buildVo.setBuildName(buildOrg.getOrgName());
                buildVo.setBusinessType(buildOrg.getBusinessTypeName());
                buildVo.setFreeType(buildOrg.getFreeTypeName());
                buildVo.setProType(buildOrg.getProTypeName());

                if(buildOrg.getSupplyTime() != null){
                    buildVo.setSupplyTime(buildOrg.getSupplyTime().toLocalDate());
                }
                if(buildOrg.getSupplyTimeActual() != null){
                    buildVo.setSupplyTimeActual(buildOrg.getSupplyTimeActual().toLocalDate());
                }
                if(buildOrg.getSupplyTimeVirtual() != null){
                    buildVo.setSupplyTimeVirtual(buildOrg.getSupplyTimeVirtual().toLocalDate());
                }

                if (buildOrg.getIsParking().equals(IsDeleteEnum.NO.getKey())) {
                    buildVo.setAveragePrice(NumberUtils.fmtTo((buildOrg.getAveragePriceHouse() == null ? new BigDecimal(0) : buildOrg.getAveragePriceHouse())));
                    buildVo.setNum((buildOrg.getRoomNum() == null ? "0" : buildOrg.getRoomNum()) + "");
                    buildVo.setArea((buildOrg.getSaleArea() == null ? "0" : buildOrg.getSaleArea()) + "");
                    buildVo.setPrice(NumberUtils.fmtToWanUnit((buildOrg.getHouseCommodityValue() == null ? "0" : buildOrg.getHouseCommodityValue()).toString()));
                } else {
                    buildVo.setAveragePrice(NumberUtils.fmtTo((buildOrg.getAveragePriceParking() == null ? new BigDecimal(0) : buildOrg.getAveragePriceParking())));
                    buildVo.setNum((buildOrg.getParkingNum() == null ? "0" : buildOrg.getParkingNum()) + "");
                    buildVo.setPrice(NumberUtils.fmtToWanUnit((buildOrg.getNotCommodityValue() == null ? "0" : buildOrg.getNotCommodityValue()).toString()));

                    buildVo.setNotNum((buildOrg.getForsaleParkingNum() == null ? "" : buildOrg.getForsaleParkingNum()) + "");
                    buildVo.setNotPrice(NumberUtils.fmtToWanUnit((buildOrg.getCommodityValue() == null ? "" : buildOrg.getCommodityValue()).toString()));
                }

                result.add(buildVo);

                if (buildOrg.getIsParking().equals(IsDeleteEnum.YES.getKey())){
                    if (CollectionUtils.isNotEmpty(parkingOrgs)){
                        for (PriceValueOrg parkingOrg : parkingOrgs){
                            if (parkingOrg.getPid().equals(buildId)) {
                                warPlanExportParkingItemInfo(result, priceVersion, mdmProject, partner, stageOrg, groupOrg, productOrg, buildOrg, parkingOrg);
                            }
                        }
                    }
                }else{
                    if (CollectionUtils.isNotEmpty(houseOrgs)) {
                        for (PriceValueOrg houseOrg : houseOrgs) {
                            warPlanExportIHouseItemInfo(result, priceVersion, mdmProject, partner, stageOrg, groupOrg, productOrg, buildOrg, buildId, houseOrg);
                        }
                    }
                }
            }
        }
    }

    private void warPlanExportIHouseItemInfo(List<PriceExcelExportVO> result, PriceVersion priceVersion, MdmProject mdmProject, StagePartNers partner, PriceValueOrg stageOrg, PriceValueOrg groupOrg, PriceValueOrg productOrg, PriceValueOrg buildOrg, String buildId, PriceValueOrg houseOrg) {
        if (houseOrg.getPid().equals(buildId)){
            PriceExcelExportVO houseVo = new PriceExcelExportVO();
            houseVo.setType(houseOrg.getType());
            houseVo.setProjectName(mdmProject.getProjectName());
            houseVo.setProjectCode(mdmProject.getProjectCode());

            houseVo.setStageName(stageOrg.getOrgName());
            houseVo.setStageCode(priceVersion.getStageCode());
            houseVo.setStageEquityRatio(partner.getEquityRatio()+"%");
            houseVo.setIsMarket(priceVersion.getIsMarket().equals(MarketingEunm.IS_MARKET.getKey())?MarketingEunm.IS_MARKET.getValue():MarketingEunm.IS_NOT_MARKET.getValue());
            houseVo.setPartTable(partner.getPartNerIsAndTable().equals("1")?"是":"否");

            houseVo.setGroupName(groupOrg.getOrgName());

            houseVo.setProProductName(productOrg.getProProductType());
            houseVo.setProProductCode(productOrg.getProProductCode());
            houseVo.setProductName(productOrg.getOrgName());
            houseVo.setProductCode(productOrg.getOrgCode());

            houseVo.setBuildName(buildOrg.getOrgName());
            houseVo.setBusinessType(buildOrg.getBusinessTypeName());
            houseVo.setFreeType(buildOrg.getFreeTypeName());
            houseVo.setProType(buildOrg.getProTypeName());

            houseVo.setAreaPart(houseOrg.getOrgName());
            houseVo.setAveragePrice((NumberUtils.fmtTo(houseOrg.getAveragePriceHouse()==null?new BigDecimal(0):houseOrg.getAveragePriceHouse())));
            houseVo.setNum((houseOrg.getRoomNum()==null?"0":houseOrg.getRoomNum())+"");
            houseVo.setArea((houseOrg.getSaleArea()==null?"0":houseOrg.getSaleArea())+"");
            houseVo.setPrice(NumberUtils.fmtToWanUnit((houseOrg.getHouseCommodityValue()==null?"0":houseOrg.getHouseCommodityValue()).toString()));

            result.add(houseVo);
        }
    }

    private void warPlanExportParkingItemInfo(List<PriceExcelExportVO> result, PriceVersion priceVersion, MdmProject mdmProject, StagePartNers partner, PriceValueOrg stageOrg, PriceValueOrg groupOrg, PriceValueOrg productOrg, PriceValueOrg buildOrg, PriceValueOrg parkingOrg) {
        PriceExcelExportVO ortherVo = new PriceExcelExportVO();
        ortherVo.setType(parkingOrg.getType());
        ortherVo.setProjectName(mdmProject.getProjectName());
        ortherVo.setProjectCode(mdmProject.getProjectCode());

        ortherVo.setStageName(stageOrg.getOrgName());
        ortherVo.setStageCode(priceVersion.getStageCode());
        ortherVo.setStageEquityRatio(partner.getEquityRatio()+"%");
        ortherVo.setIsMarket(priceVersion.getIsMarket().equals(MarketingEunm.IS_MARKET.getKey())?MarketingEunm.IS_MARKET.getValue():MarketingEunm.IS_NOT_MARKET.getValue());
        ortherVo.setPartTable(partner.getPartNerIsAndTable().equals("1")?"是":"否");

        ortherVo.setGroupName(groupOrg.getOrgName());

        ortherVo.setProProductName(productOrg.getProProductType());
        ortherVo.setProProductCode(productOrg.getProProductCode());
        ortherVo.setProductName(productOrg.getOrgName());
        ortherVo.setProductCode(productOrg.getOrgCode());

        ortherVo.setBuildName(buildOrg.getOrgName());
        ortherVo.setBusinessType(buildOrg.getBusinessTypeName());
        ortherVo.setFreeType(buildOrg.getFreeTypeName());
        ortherVo.setProType(buildOrg.getProTypeName());

        ortherVo.setAreaPart(parkingOrg.getOrgName());

        if (parkingOrg.getType().equals(OrgTypeEunm.ORG_NOT_SALING_PARKING.getKey())){
            ortherVo.setAveragePrice(NumberUtils.fmtTo(StrUtils.bigDecimalDIV(parkingOrg.getCommodityValue(), new BigDecimal(parkingOrg.getForsaleParkingNum()))));
            ortherVo.setNotNum((parkingOrg.getForsaleParkingNum()==null?"0":parkingOrg.getForsaleParkingNum())+"");
            ortherVo.setNotPrice(NumberUtils.fmtToWanUnit((parkingOrg.getCommodityValue()==null?"0":parkingOrg.getCommodityValue()).toString()));
        }else{
            ortherVo.setAveragePrice(NumberUtils.fmtTo((parkingOrg.getAveragePriceParking()==null?new BigDecimal(0):parkingOrg.getAveragePriceParking())));
            ortherVo.setNum((parkingOrg.getParkingNum()==null?"0":parkingOrg.getParkingNum())+"");
            ortherVo.setPrice(NumberUtils.fmtToWanUnit((parkingOrg.getNotCommodityValue()==null?"0":parkingOrg.getNotCommodityValue()).toString()));
        }
        result.add(ortherVo);
    }

    /**
     * 版本对比
     */
    @Override
    public DifferenceReviewVersionVO valueDifferenceReview(String code, List<PriceCompareVersionIdsVO> priceCompareVersionIdsVOs) {
        DifferenceReviewVersionVO resultList = new DifferenceReviewVersionVO();

        ValueReviewVersionContentVO masterVersionVo = new ValueReviewVersionContentVO();
        ValueReviewVersionContentVO slaveVersionVo = new ValueReviewVersionContentVO();
        DifferenceReviewVO differenceVo = new DifferenceReviewVO();

        if(CollectionUtils.isEmpty(priceCompareVersionIdsVOs)){
            resultList.setMessage(CodeEnum.ILLEGAL_REQUEST_PARAM_ERROR.getMessage());
            return resultList;
        }
        for (PriceCompareVersionIdsVO idVos : priceCompareVersionIdsVOs) {
            priceCompareVersionInfo(masterVersionVo, slaveVersionVo, idVos);
        }

        priceCompareBasicInfo(masterVersionVo, slaveVersionVo, differenceVo);

        resultList.setAfterContentVO(masterVersionVo);
        resultList.setContentVO(slaveVersionVo);
        resultList.setDifferenceVO(differenceVo);
        return resultList;
    }

    private void priceCompareBasicInfo(ValueReviewVersionContentVO masterVersionVo, ValueReviewVersionContentVO slaveVersionVo, DifferenceReviewVO differenceVo) {
        //总货值
        BigDecimal totalValueDiff = BigDecimalSUB(masterVersionVo.getTotalValue(), slaveVersionVo.getTotalValue());
        if (totalValueDiff.compareTo(BigDecimal.ZERO)!=0 && (slaveVersionVo.getTotalValue()).compareTo(BigDecimal.ZERO)!=0){
            BigDecimal totalValuePer = StrUtils.bigDecimalDIV(totalValueDiff, slaveVersionVo.getTotalValue());
            differenceVo.setTotalValuePer(totalValuePer);
        }else {
            differenceVo.setTotalValuePer(BigDecimal.ZERO);
        }
        differenceVo.setTotalValueDiff(totalValueDiff);

        //权益货值
        BigDecimal quityValueDiff = BigDecimalSUB(masterVersionVo.getQuityValue(), slaveVersionVo.getQuityValue());
        if (quityValueDiff.compareTo(BigDecimal.ZERO)!=0 && (slaveVersionVo.getQuityValue()).compareTo(BigDecimal.ZERO)!=0){
            BigDecimal quityValuePer = StrUtils.bigDecimalDIV(quityValueDiff, slaveVersionVo.getQuityValue());
            differenceVo.setQuityValuePer(quityValuePer);
        }else {
            differenceVo.setQuityValuePer(BigDecimal.ZERO);
        }
        differenceVo.setQuityValueDiff(quityValueDiff);

        //房源货值
        BigDecimal houseCommodityValueCountDiff = BigDecimalSUB(masterVersionVo.getHouseCommodityValueCount(), slaveVersionVo.getHouseCommodityValueCount());
        if (houseCommodityValueCountDiff.compareTo(BigDecimal.ZERO)!=0 && (slaveVersionVo.getHouseCommodityValueCount()).compareTo(BigDecimal.ZERO)!=0){
            BigDecimal houseCommodityValueCountPer = StrUtils.bigDecimalDIV(houseCommodityValueCountDiff, slaveVersionVo.getHouseCommodityValueCount());
            differenceVo.setHouseCommodityValueCountPer(houseCommodityValueCountPer);
        }else {
            differenceVo.setHouseCommodityValueCountPer(BigDecimal.ZERO);
        }
        differenceVo.setHouseCommodityValueCountDiff(houseCommodityValueCountDiff);

        //房源均价
        BigDecimal houseAvgDiff = BigDecimalSUB(masterVersionVo.getHouseAvg(), slaveVersionVo.getHouseAvg());
        if (houseAvgDiff.compareTo(BigDecimal.ZERO)!=0 && (slaveVersionVo.getHouseAvg()).compareTo(BigDecimal.ZERO)!=0){
            BigDecimal houseAvgPer = StrUtils.bigDecimalDIV(houseAvgDiff, slaveVersionVo.getHouseAvg());
            differenceVo.setHouseAvgPer(houseAvgPer);
        }else {
            differenceVo.setHouseAvgPer(BigDecimal.ZERO);
        }
        differenceVo.setHouseAvgDiff(houseAvgDiff);

        //房源面积
        BigDecimal saleAreaCountDiff = BigDecimalSUB(masterVersionVo.getSaleAreaCount(), slaveVersionVo.getSaleAreaCount());
        if (saleAreaCountDiff.compareTo(BigDecimal.ZERO)!=0 && (slaveVersionVo.getSaleAreaCount()).compareTo(BigDecimal.ZERO)!=0){
            BigDecimal saleAreaCountPer = StrUtils.bigDecimalDIV(saleAreaCountDiff, slaveVersionVo.getSaleAreaCount());
            differenceVo.setSaleAreaCountPer(saleAreaCountPer);
        }else {
            differenceVo.setSaleAreaCountPer(BigDecimal.ZERO);
        }
        differenceVo.setSaleAreaCountDiff(saleAreaCountDiff);

        //总房源
        int roomNumCountDiff = masterVersionVo.getRoomNumCount() - slaveVersionVo.getRoomNumCount();
        if (slaveVersionVo.getRoomNumCount() != 0){
            BigDecimal roomNumCountDiffB = new BigDecimal(roomNumCountDiff);
            BigDecimal roomNumCountB = new BigDecimal(slaveVersionVo.getRoomNumCount());
            BigDecimal roomNumCountPer = StrUtils.bigDecimalDIV(roomNumCountDiffB, roomNumCountB);
            differenceVo.setRoomNumCountPer(roomNumCountPer);
        }else {
            differenceVo.setRoomNumCountPer(BigDecimal.ZERO);
        }
        differenceVo.setRoomNumCountDiff(roomNumCountDiff);

        //可售车位货值
        BigDecimal parkingValueCountDiff = BigDecimalSUB(masterVersionVo.getParkingValueCount(), slaveVersionVo.getParkingValueCount());
        if (parkingValueCountDiff.compareTo(BigDecimal.ZERO) != 0 && (slaveVersionVo.getParkingValueCount()).compareTo(BigDecimal.ZERO)!=0){
            BigDecimal parkingValueCountPer = StrUtils.bigDecimalDIV(parkingValueCountDiff, slaveVersionVo.getParkingValueCount());
            differenceVo.setParkingValueCountPer(parkingValueCountPer);
        }else {
            differenceVo.setParkingValueCountPer(BigDecimal.ZERO);
        }
        differenceVo.setParkingValueCountDiff(parkingValueCountDiff);

        //可售车位均价
        BigDecimal parkingAvgDiff = BigDecimalSUB(masterVersionVo.getParkingAvg(), slaveVersionVo.getParkingAvg());
        if (parkingAvgDiff.compareTo(BigDecimal.ZERO)!=0 && (slaveVersionVo.getParkingAvg()).compareTo(BigDecimal.ZERO)!=0){
            BigDecimal parkingAvgPer = StrUtils.bigDecimalDIV(parkingAvgDiff, slaveVersionVo.getParkingAvg());
            differenceVo.setParkingAvgPer(parkingAvgPer);
        }else {
            differenceVo.setParkingAvgPer(BigDecimal.ZERO);
        }
        differenceVo.setParkingAvgDiff(parkingAvgDiff);

        //可售车位数
        int parkingNumCountDiff = masterVersionVo.getParkingNumCount() - slaveVersionVo.getParkingNumCount();
        if (slaveVersionVo.getParkingNumCount() != 0){
            BigDecimal parkingNumCountDiffB = new BigDecimal(parkingNumCountDiff);
            BigDecimal parkingNumCountB = new BigDecimal(slaveVersionVo.getParkingNumCount());
            BigDecimal parkingNumCountPer = StrUtils.bigDecimalDIV(parkingNumCountDiffB, parkingNumCountB);
            differenceVo.setParkingNumCountPer(parkingNumCountPer);
        }else {
            differenceVo.setParkingNumCountPer(BigDecimal.ZERO);
        }
        differenceVo.setParkingNumCountDiff(parkingNumCountDiff);

        //未推售车位货值
        BigDecimal forSaleParkingValueCountDiff = BigDecimalSUB(masterVersionVo.getForSaleParkingValueCount(), slaveVersionVo.getForSaleParkingValueCount());
        if (forSaleParkingValueCountDiff.compareTo(BigDecimal.ZERO) != 0 && (slaveVersionVo.getForSaleParkingValueCount()).compareTo(BigDecimal.ZERO)!=0){
            BigDecimal forSaleParkingValueCountPer = StrUtils.bigDecimalDIV(forSaleParkingValueCountDiff, slaveVersionVo.getForSaleParkingValueCount());
            differenceVo.setForSaleParkingValueCountPer(forSaleParkingValueCountPer);
        }else {
            differenceVo.setForSaleParkingValueCountPer(BigDecimal.ZERO);
        }
        differenceVo.setForSaleParkingValueCountDiff(forSaleParkingValueCountDiff);

        //未推售车位数
        int forSaleParkingNumCountDiff = masterVersionVo.getForSaleParkingNumCount() - slaveVersionVo.getForSaleParkingNumCount();
        if (slaveVersionVo.getForSaleParkingNumCount() != 0){
            BigDecimal forSaleParkingNumCountDiffB = new BigDecimal(forSaleParkingNumCountDiff);
            BigDecimal forSaleParkingNumCountB = new BigDecimal(slaveVersionVo.getForSaleParkingNumCount());
            BigDecimal forSaleparkingNumCountPer = StrUtils.bigDecimalDIV(forSaleParkingNumCountDiffB, forSaleParkingNumCountB);
            differenceVo.setForSaleParkingNumCountPer(forSaleparkingNumCountPer);
        }else {
            differenceVo.setForSaleParkingNumCountPer(BigDecimal.ZERO);
        }
        differenceVo.setForSaleParkingNumCountDiff(forSaleParkingNumCountDiff);
    }

    private void priceCompareVersionInfo(ValueReviewVersionContentVO masterVersionVo, ValueReviewVersionContentVO slaveVersionVo, PriceCompareVersionIdsVO idVos) {
        String masterVersionId = idVos.getMasterVersionId();
        if (StringUtils.isNotEmpty(masterVersionId)){
            PriceVersion masterPriceVersion = priceVersionMapper.selectByVersionId(masterVersionId, IsDeleteEnum.NO.getKey());
            if (masterPriceVersion != null){
                BigDecimal equityRatio = new BigDecimal(0);
                StagePartNers stagePartner = stagePartNersService.getStagePartnersByProjectFid(masterPriceVersion.getProjectfId());
                if(stagePartner != null){
                    equityRatio = new BigDecimal(stagePartner.getEquityRatio()==null?"0":stagePartner.getEquityRatio())
                            .divide(new BigDecimal(100), 4, RoundingMode.HALF_UP);
                }

                QueryWrapper<PriceValueOrg> stageWrapper = new QueryWrapper<PriceValueOrg>();
                stageWrapper.eq("version_id", masterVersionId)
                        .eq("type", OrgTypeEunm.ORG_STAGE.getKey())
                        .eq("is_delete", IsDeleteEnum.NO.getKey());
                PriceValueOrg masterProjectFOrgs = priceValueOrgMapper.selectOne(stageWrapper);

                setCompareVersionVoInfo(masterVersionVo, equityRatio, masterProjectFOrgs);
            }
        }

        String slaveVersionId = idVos.getSlaveVersionId();
        if (StringUtils.isNotEmpty(slaveVersionId)){
            PriceVersion slavePriceVersion = priceVersionMapper.selectByVersionId(slaveVersionId, IsDeleteEnum.NO.getKey());
            if (slavePriceVersion != null){
                BigDecimal equityRatio = new BigDecimal(0);
                StagePartNers stagePartner = stagePartNersService.getStagePartnersByProjectFid(slavePriceVersion.getProjectfId());
                if (stagePartner != null){
                    equityRatio = new BigDecimal(stagePartner.getEquityRatio()==null?"0":stagePartner.getEquityRatio())
                            .divide(new BigDecimal(100), 4, RoundingMode.HALF_UP);
                }

                QueryWrapper<PriceValueOrg> stageWrapper = new QueryWrapper<PriceValueOrg>();
                stageWrapper.eq("version_id", slaveVersionId)
                        .eq("type", OrgTypeEunm.ORG_STAGE.getKey())
                        .eq("is_delete", IsDeleteEnum.NO.getKey());
                PriceValueOrg slaveProjectFOrgs = priceValueOrgMapper.selectOne(stageWrapper);

                setCompareVersionVoInfo(slaveVersionVo, equityRatio, slaveProjectFOrgs);
            }
        }
    }

    private void setCompareVersionVoInfo(ValueReviewVersionContentVO masterVersionVo, BigDecimal equityRatio, PriceValueOrg masterProjectFOrgs) {
        masterVersionVo.setRoomNumCount(masterVersionVo.getRoomNumCount() + masterProjectFOrgs.getRoomNum());
        masterVersionVo.setParkingNumCount(masterVersionVo.getParkingNumCount() + masterProjectFOrgs.getParkingNum());
        masterVersionVo.setForSaleParkingNumCount(masterVersionVo.getForSaleParkingNumCount() + masterProjectFOrgs.getForsaleParkingNum());
        masterVersionVo.setHouseCommodityValueCount(BigDecimalADD(masterVersionVo.getHouseCommodityValueCount(), masterProjectFOrgs.getHouseCommodityValue()));
        masterVersionVo.setParkingValueCount(BigDecimalADD(masterVersionVo.getParkingValueCount(), masterProjectFOrgs.getNotCommodityValue()));
        masterVersionVo.setForSaleParkingValueCount(BigDecimalADD(masterVersionVo.getForSaleParkingValueCount(), masterProjectFOrgs.getCommodityValue()));
        masterVersionVo.setSaleAreaCount(BigDecimalADD(masterVersionVo.getSaleAreaCount(), masterProjectFOrgs.getSaleArea()));
        BigDecimal totalValue = BigDecimalADD(masterProjectFOrgs.getHouseCommodityValue(), masterProjectFOrgs.getNotCommodityValue());
        masterVersionVo.setTotalValue(BigDecimalADD(masterVersionVo.getTotalValue(), totalValue));
        masterVersionVo.setHouseAvg(BigDecimalADD(masterVersionVo.getHouseAvg(), masterProjectFOrgs.getAveragePriceHouse()));
        masterVersionVo.setParkingAvg(BigDecimalADD(masterVersionVo.getParkingAvg(), masterProjectFOrgs.getAveragePriceParking()));
        BigDecimal equityRatioValue = StrUtils.BigDecimalMUL(totalValue, equityRatio);
        masterVersionVo.setQuityValue(BigDecimalADD(masterVersionVo.getQuityValue(), equityRatioValue));
    }

    /**
     * 修改货值版本号、版本名称和归属月
     */
    @Override
    @Transactional
    public void updateAfterAscriptionVersion(PriceVersion notFinishVersion, LocalDateTime afterNow, LocalDate afterAscriptionDate) {
        notFinishVersion.setVersionNum("V1");
        notFinishVersion.setVersionName(VersionTypeEunm.getValueByKey(notFinishVersion.getVersionType()));
        notFinishVersion.setAscriptionDate(afterAscriptionDate);
        notFinishVersion.setUpdateTime(afterNow);
        priceVersionMapper.updateByPrimaryKeySelective(notFinishVersion);

        try{
            versionLogService.saveVersionLogInfo(notFinishVersion.getProjectId(), notFinishVersion.getProjectfId(), ModuleTypeEunm.PRICE.getKey(), VersionEventEnum.UPDATE_SAVE.getKey(),
                    notFinishVersion.getId(), VersionNameUtils.getVersionName(notFinishVersion), notFinishVersion.getVersionState(),
                    notFinishVersion.getVersionState(), "", null, Constants.SYS, afterNow, "货值迁移版本", null, IsDeleteEnum.NO.getKey(), Constants.SYS, LocalDateTime.now());
        }catch (Exception e){
            logger.error("################ updateAfterAscriptionVersion versionLog error : "+e);
        }
    }

    /**
     * 保存货值版本信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void refreshSaveInfo(PriceVersion oldPriceVersion, List<PriceValueOrg> projectFList, List<PriceValueOrg> groupInsertList, List<PriceValueOrg> productInsertList, List<PriceValueOrg> buildInsertList, List<PriceValueOrg> hoseSoleList, List<PriceValueOrg> parkSoleList, LocalDateTime now) {

        QueryWrapper<PriceValueOrg> orgWrapper = new QueryWrapper<PriceValueOrg>();
        orgWrapper.eq("version_id", oldPriceVersion.getId())
                .eq("is_delete", IsDeleteEnum.NO.getKey());

        //删除之前货值信息
        priceVersionMapper.deleteByPrimaryKey(oldPriceVersion.getId());
        priceValueOrgMapper.delete(orgWrapper);

        //测试保存
        priceVersionMapper.insertRecord(oldPriceVersion);
        priceValueOrgMapper.insertBatch(projectFList);
        if (CollectionUtils.isNotEmpty(groupInsertList)) {
            priceValueOrgMapper.insertBatch(groupInsertList);
        }
        if (CollectionUtils.isNotEmpty(productInsertList)) {
            priceValueOrgMapper.insertBatch(productInsertList);
        }
        if (CollectionUtils.isNotEmpty(buildInsertList)) {
            priceValueOrgMapper.insertBatch(buildInsertList);
        }
        if (CollectionUtils.isNotEmpty(hoseSoleList)) {
            priceValueOrgMapper.insertBatch(hoseSoleList);
        }
        if (CollectionUtils.isNotEmpty(parkSoleList)) {
            priceValueOrgMapper.insertBatch(parkSoleList);
        }
    }

    /**
     *  查询指定货值
     */
    @Override
    public PriceVersion selectById(String versionId) {
        return priceVersionMapper.selectById(versionId);
    }

	@Override
	public String selectArea(String versionId, String collectType) {
		return priceVersionMapper.selectArea(versionId,collectType);
	}
	

	@Override
	public List<GroupPriceVersionListVO> selectGroupPriceVersionList(String projectId) {
		return priceVersionGroupMapper.selectGroupPriceVersionList(projectId);
	}

	@Override
	public List<GroupPriceDetailVO> selectGroupPriceVersion(String versionId) {
		List<GroupPriceDetailVO> result = Collections.synchronizedList(new ArrayList<>());
		List<GroupPriceDetailVO> lastList = Collections.synchronizedList(new ArrayList<>());
		String projectId="";
		List<PriceVersionGroup> versionList = priceVersionGroupMapper.selectByVersionId(versionId);
		List<String> versionIds = new ArrayList<>();
		for(PriceVersionGroup version : versionList) {
			projectId = version.getProjectId();
			versionIds.add(version.getId());
			List<PriceValueOrgGroup> detail = priceValueOrgGroupMapper.selectByVersionId(version.getId());  
			w : for(PriceValueOrgGroup org : detail) {
				if(org.getBusinessType() != null && (org.getBusinessType().equals(SalyTypeEnum.NOT_RENTABLE.getKey()) || org.getBusinessType().equals(SalyTypeEnum.RENTED.getKey()))) {
					continue w;
				}
				GroupPriceDetailVO vo = new GroupPriceDetailVO();
			    vo.setId(org.getId());
			    if(org.getType().equals(OrgTypeEunm.ORG_STAGE.getKey())) {
			    	vo.setPid(projectId);
			    }else {
			    	vo.setPid(org.getPid());
			    }
			    vo.setName(org.getOrgName());
			    vo.setCode(org.getOrgCode());
			    vo.setType(org.getType());
			    vo.setIsParking(org.getIsParking());
			    vo.setIsSupply(org.getIsSupply());
			    if(org.getSupplyTimeVirtual() != null){
			    	vo.setSupplyDate(org.getSupplyTimeVirtual());
		        }else{
		            if (org.getSupplyTimeActual() != null) {
		            	vo.setSupplyDate(org.getSupplyTimeActual());
		            } else {
		            	vo.setSupplyDate(org.getSupplyTime());
		            }
		        }
			    vo.setBusinessTypeCode(org.getBusinessType());
			    vo.setBusinessTypeName(org.getBusinessTypeName());
			    vo.setFreeTypeCode(org.getFreeType());
			    vo.setFreeTypeName(org.getFreeTypeName());
			    vo.setProTypeCode(org.getProType());
			    vo.setProTypeName(org.getProTypeName());
			    vo.setProProductCode(org.getProProductCode());
			    vo.setProProductName(org.getProProductType());
			    vo.setProductCode(org.getProductCode());
			    vo.setProductName(org.getProductType());
			    vo.setNumHouse(org.getRoomNum());
			    vo.setNumParking(org.getParkingNum());
			    vo.setSaleArea(org.getSaleArea());
			    vo.setAveragePriceHouse(org.getAveragePriceHouse());
			    vo.setAveragePriceParking(org.getAveragePriceParking());
			    vo.setCommodityValue(org.getCommodityValue());
			    vo.setHousecontainCommodityValue(org.getHouseCommodityValue());
			    vo.setNumParkingForsale(org.getForsaleParkingNum());
			    vo.setNocontainCommodityValue(org.getNotCommodityValue());
			    result.add(vo);
			}
		}
		//项目层级
		PriceValueOrgGroup org = priceValueOrgGroupMapper.selectStageDetail(versionIds,OrgTypeEunm.ORG_STAGE.getKey(),IsDeleteEnum.NO.getKey());
		MdmProject project = projectService.selectByProjectId(projectId, IsDeleteEnum.NO.getKey());
		List<PriceCoreDetail> core = priceCoreDetailMapper.selectByVersionId(versionId);
		GroupPriceDetailVO vo = new GroupPriceDetailVO();
		vo.setId(projectId);
		vo.setPid("0");
	    vo.setName(project.getProjectName());
	    vo.setCode(project.getProjectCode());
	    vo.setType(OrgTypeEunm.ORG_PRODUCTF.getKey());
	    vo.setNumHouse(org.getRoomNum());
	    vo.setNumParking(org.getParkingNum());
	    vo.setSaleArea(org.getSaleArea());
	    vo.setAveragePriceHouse(NumberUtils.divide(org.getHouseCommodityValue(), org.getSaleArea(), 0));
	    vo.setAveragePriceParking(NumberUtils.divide(org.getNotCommodityValue(), org.getParkingNum() == null ? BigDecimal.ZERO : new BigDecimal(org.getParkingNum()), 0));
	    vo.setNocontainCommodityValue(org.getNotCommodityValue());
	    vo.setHousecontainCommodityValue(org.getHouseCommodityValue());
	    vo.setNumParkingForsale(org.getForsaleParkingNum());
	    vo.setCommodityValue(org.getCommodityValue());
	    //核心指标
	    vo.setInvestment(prepareGroupCorePriceDetail("investment",core));
	    vo.setStrategy(prepareGroupCorePriceDetail("strategy",core));
	    vo.setGroup(prepareGroupCorePriceDetail("group",core));
	    vo.setBefore(prepareGroupCorePriceDetail("before",core));
	    vo.setAfter(prepareGroupCorePriceDetail("after",core));
	    
	    lastList.add(vo);
	    
	    //排序
		List<GroupPriceDetailVO> stageList = Collections.synchronizedList(new ArrayList<>());
		List<GroupPriceDetailVO> groupList = Collections.synchronizedList(new ArrayList<>());
		List<GroupPriceDetailVO> batchList = Collections.synchronizedList(new ArrayList<>());
		List<GroupPriceDetailVO> productList = Collections.synchronizedList(new ArrayList<>());
		List<GroupPriceDetailVO> buildList = Collections.synchronizedList(new ArrayList<>());
		List<GroupPriceDetailVO> houseList = Collections.synchronizedList(new ArrayList<>());
		List<GroupPriceDetailVO> otherList = Collections.synchronizedList(new ArrayList<>());
		
		result.forEach(x->{
			 String typeTemp = x.getType();
			 if(typeTemp.equals(OrgTypeEunm.ORG_STAGE.getKey())){
				stageList.add(x);
	         }else if(typeTemp.equals(OrgTypeEunm.ORG_GROUP.getKey())){
	        	 groupList.add(x);
		     }else if(typeTemp.equals(OrgTypeEunm.ORG_BATCH.getKey())){
		    	 batchList.add(x);
		     } else if(typeTemp.equals(OrgTypeEunm.ORG_PRODUCT.getKey())){
		    	 productList.add(x);
		     }else if(typeTemp.equals(OrgTypeEunm.ORG_BUILD.getKey())){
		    	 buildList.add(x);
		     }else if(typeTemp.equals(OrgTypeEunm.ORG_HOUSE_PACKAGE.getKey())){
		    	 houseList.add(x);
		     }else {
		    	 otherList.add(x);
	         }
		});
		
		
		//排序
		if(CollectionUtils.isNotEmpty(stageList)){
			List<GroupPriceDetailVO> sortList = stageList.parallelStream().sorted((a, b) -> {
			    String aStageName = StrUtils.nvl(a.getName());
			    String bStageName = StrUtils.nvl(b.getName());
			    if (!aStageName.equals(bStageName)) {
			    	return ReportUtils.compareStrStartedChinaNum(aStageName, bStageName);
			    }
			    return 0;
			}).collect(Collectors.toList());
			lastList.addAll(sortList);
	    }
		if(CollectionUtils.isNotEmpty(groupList)){
			groupList.sort((a, b) -> {
	            return groupExportSortInfo(a.getName(), b.getName(), Constants.PARKING_NAME);
	        });
			lastList.addAll(groupList);
		}
		
		if(CollectionUtils.isNotEmpty(batchList)){
			batchList.sort((a, b) -> {
	            String aName = a.getName();
	            String bName = b.getName();
	
	            String[] aStr = aName.split("批次");
	            String[] bStr = bName.split("批次");
	
	            String aValue = NumberEnum.getKeyByValue(aStr[0]);
	            String bValue = NumberEnum.getKeyByValue(bStr[0]);
	
	            return aValue == null ? 1 : bValue == null ? -1 : Integer.valueOf(aValue) - Integer.valueOf(bValue);
	        });
			lastList.addAll(batchList);
		}
		
		if(CollectionUtils.isNotEmpty(productList)){
			productList.sort((a, b) -> {
	            String aCode = a.getCode();
	            String bCode = b.getCode();
	
	            return aCode == null ? 1 : bCode == null ? -1 : Integer.valueOf(aCode) - Integer.valueOf(bCode);
	        });
			lastList.addAll(productList);
		}
		lastList.addAll(buildList);
		
		
		if(CollectionUtils.isNotEmpty(houseList)){
			houseList.sort((a, b) -> {
	            String aName = a.getName();
	            String bName = b.getName();
	
	            String aStr = "";
	            String bStr = "";
	
	            String[] aSplit = aName.split("-");
	            String[] bSplit = bName.split("-");
	
	            aStr = aSplit[0];
	            bStr = bSplit[0];
	
	            if (aName.equals(Constants.ORTHER_HOUSE_NAME)) {
	                aStr = "10000000";
	            }
	            if (bName.equals(Constants.ORTHER_HOUSE_NAME)) {
	                bStr = "10000000";
	            }
	
	            return aStr == null ? 1 : bStr == null ? -1 : Integer.valueOf(aStr) - Integer.valueOf(bStr);
	         });
			 lastList.addAll(houseList);
		   }
		 lastList.addAll(otherList);
		
		return lastList;
	}

	private GroupCorePriceDetailVO prepareGroupCorePriceDetail(String type, List<PriceCoreDetail> core) {
		GroupCorePriceDetailVO obj = new GroupCorePriceDetailVO();
		obj.setEquityPrice(getCoreValue(type,CoreWarnItemEnum.EQUITYPRICE.getKey(),core));
		obj.setEquityBeforeProfit(getCoreValue(type,CoreWarnItemEnum.EQUITYBEFOREPROFIT.getKey(),core));
		obj.setEquityAfterProfit(getCoreValue(type,CoreWarnItemEnum.EQUITYAFTERPROFIT.getKey(),core));
		obj.setCreateProfit(getCoreValue(type,CoreWarnItemEnum.CREATEPROFIT.getKey(),core));
		obj.setMeltingIRR(getCoreValue(type,CoreWarnItemEnum.MELTINGIRR.getKey(),core));
		obj.setMeltingInvestment(getCoreValue(type,CoreWarnItemEnum.MELTINGINVESTMENT.getKey(),core));
		return obj;
	}

	private BigDecimal getCoreValue(String type,String key, List<PriceCoreDetail> core) {
		for(PriceCoreDetail detail : core) {
			if(key.equals(detail.getType())) {
				switch (type) {
				case "investment":
					return detail.getInvestment();
				case "strategy":
					return detail.getStrategy();
				case "group":
					return detail.getGroup();
				case "before":
					return detail.getBefore();
				case "after":
					return detail.getAfter();
				default:
					return null;
				}
			}
		}
		return null;
	}
	

}
